"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { Button, Card, Col, Input, Row, Select, Space, Table, Tag, Tooltip, Typography, message } from "antd";
import type { ColumnsType, TablePaginationConfig } from "antd/es/table";
import { ReloadOutlined } from "@ant-design/icons";
import dayjs from "dayjs";

import { fetchCaasmIPAssets, fetchCaasmServices } from "@/lib/api/caasm";
import type { CaasmIPAsset } from "@/types/models";

const { Title, Text } = Typography;

const exposureOptions = [
  { label: "Public", value: "public" },
  { label: "Private", value: "private" },
];

const providerOptions = [
  { label: "AWS", value: "aws" },
  { label: "GCP", value: "gcp" },
  { label: "Azure", value: "azure" },
  { label: "Alibaba", value: "alibaba" },
  { label: "GoDaddy", value: "godaddy" },
  { label: "Other", value: "other" },
];

const providerColors: Record<string, string> = {
  aws: "gold",
  gcp: "red",
  azure: "blue",
  alibaba: "orange",
  godaddy: "purple",
  other: "default",
};

const DEFAULT_IP_ASSET_STALE_AFTER_HOURS = 6;

const freshnessColors: Record<string, string> = {
  fresh: "green",
  stale: "gold",
  deleted: "red",
};

const wrapTextStyle = {
  display: "inline-block",
  maxWidth: "100%",
  overflowWrap: "anywhere",
  whiteSpace: "normal",
  wordBreak: "break-word",
} as const;

type IPAssetFilters = {
  q?: string;
  exposure?: "public" | "private";
  provider?: string;
  asset_service?: string;
  region?: string;
};

function formatDate(value?: string) {
  if (!value) return "-";
  return dayjs(value).format("YYYY-MM-DD HH:mm");
}

function formatProvider(value?: string) {
  if (!value) return "-";
  return value.toUpperCase();
}

function formatExposure(record: CaasmIPAsset) {
  return record.exposure || (record.is_public ? "public" : "private");
}

function isLiteralIPAddress(value?: string) {
  const trimmed = value?.trim();
  if (!trimmed) return false;
  const ipv4Pattern =
    /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}$/;
  const ipv6Pattern = /^[0-9a-f:]+$/i;
  return ipv4Pattern.test(trimmed) || (trimmed.includes(":") && ipv6Pattern.test(trimmed));
}

function getFreshnessState(record: CaasmIPAsset) {
  if (record.freshness_state) {
    return record.freshness_state;
  }
  if (record.deleted_at) {
    return "deleted";
  }
  if (typeof record.stale === "boolean") {
    return record.stale ? "stale" : "fresh";
  }
  if (typeof record.is_stale === "boolean") {
    return record.is_stale ? "stale" : "fresh";
  }
  if (!record.last_seen_at) {
    return "stale";
  }
  const lastSeen = dayjs(record.last_seen_at);
  if (!lastSeen.isValid()) {
    return "stale";
  }
  const staleAfterHours = record.stale_after_hours ?? DEFAULT_IP_ASSET_STALE_AFTER_HOURS;
  return dayjs().diff(lastSeen, "hour", true) > staleAfterHours ? "stale" : "fresh";
}

function freshnessTooltip(record: CaasmIPAsset) {
  if (record.freshness_state) {
    return `Freshness reported by API as ${record.freshness_state}.`;
  }
  if (typeof record.stale === "boolean" || typeof record.is_stale === "boolean") {
    return "Freshness derived from the API stale boolean.";
  }
  if (!record.last_seen_at) {
    return "No last_seen_at is available, so the row is treated as stale.";
  }
  return `Fallback freshness uses last_seen_at and a ${record.stale_after_hours ?? DEFAULT_IP_ASSET_STALE_AFTER_HOURS} hour stale window.`;
}

function stringFromUnknown(value: unknown) {
  if (typeof value === "string") {
    return value.trim();
  }
  if (typeof value === "number" || typeof value === "boolean") {
    return String(value);
  }
  return "";
}

function firstString(...values: unknown[]) {
  for (const value of values) {
    const text = stringFromUnknown(value);
    if (text) {
      return text;
    }
  }
  return "";
}

function metadataString(record: CaasmIPAsset, keys: string[]) {
  const metadata = record.asset?.metadata;
  if (!metadata) {
    return "";
  }
  return firstString(...keys.map((key) => metadata[key]));
}

function getSourceService(record: CaasmIPAsset) {
  return firstString(
    record.source_service,
    metadataString(record, ["source_service", "ip_source_service", "aws_service"]),
    record.asset?.service,
  );
}

function getOwningResource(record: CaasmIPAsset) {
  return firstString(
    record.owning_resource,
    record.owning_resource_id,
    record.resource_id,
    metadataString(record, ["owning_resource", "owning_resource_id", "resource_id", "native_id", "arn"]),
    record.asset?.native_id,
    record.asset?.name,
  );
}

function renderWrappedValue(value?: string, fallback = "-") {
  const text = value || fallback;
  return (
    <Tooltip title={text}>
      <Text style={wrapTextStyle}>{text}</Text>
    </Tooltip>
  );
}

export default function CaasmIPAssetsPage() {
  const [records, setRecords] = useState<CaasmIPAsset[]>([]);
  const [total, setTotal] = useState(0);
  const [loading, setLoading] = useState(false);
  const [filters, setFilters] = useState<IPAssetFilters>({});
  const [pagination, setPagination] = useState<TablePaginationConfig>({ current: 1, pageSize: 20 });
  const [cloudServiceOptions, setCloudServiceOptions] = useState<{ label: string; value: string }[]>([]);
  const currentPage = pagination.current ?? 1;
  const currentPageSize = pagination.pageSize ?? 20;

  const loadData = useCallback(
    async (page: number, pageSize: number) => {
      setLoading(true);
      try {
        const payload = await fetchCaasmIPAssets({
          page,
          page_size: pageSize,
          q: filters.q || undefined,
          exposure: filters.exposure,
          provider: filters.provider,
          asset_service: filters.asset_service,
          region: filters.region || undefined,
        });
        setRecords(payload.items ?? []);
        setTotal(payload.total ?? 0);
      } catch (error) {
        console.error("Failed to load IP assets", error);
        message.error("Failed to load IP assets.");
        setRecords([]);
        setTotal(0);
      } finally {
        setLoading(false);
      }
    },
    [filters],
  );

  useEffect(() => {
    const current = pagination.current ?? 1;
    const size = pagination.pageSize ?? 20;
    loadData(current, size);
  }, [loadData, pagination]);

  useEffect(() => {
    fetchCaasmServices()
      .then((services) => setCloudServiceOptions(services.map((service) => ({ label: service, value: service }))))
      .catch((error) => {
        console.error("Failed to load cloud services", error);
      });
  }, []);

  const resetFilters = useCallback(() => {
    setFilters({});
    setPagination((prev) => ({ ...prev, current: 1 }));
  }, []);

  const refresh = useCallback(() => {
    loadData(currentPage, currentPageSize);
  }, [currentPage, currentPageSize, loadData]);

  const columns: ColumnsType<CaasmIPAsset> = useMemo(
    () => [
      {
        title: "IP Address",
        dataIndex: "ip_address",
        width: 180,
        fixed: "left",
        render: (value: string) =>
          isLiteralIPAddress(value) ? (
            <Text code>{value}</Text>
          ) : (
            <Tooltip title="The API did not provide a literal IP address for this row. Hostnames are shown only in the Hostname column.">
              <Tag>Missing IP</Tag>
            </Tooltip>
          ),
      },
      {
        title: "Exposure",
        dataIndex: "exposure",
        width: 110,
        render: (_: unknown, record) => {
          const exposure = formatExposure(record);
          return <Tag color={exposure === "public" ? "red" : "blue"}>{exposure.toUpperCase()}</Tag>;
        },
      },
      {
        title: "Hostname",
        dataIndex: "hostname",
        width: 240,
        render: (value: string) => renderWrappedValue(value),
      },
      {
        title: "Source Service",
        key: "source_service",
        width: 150,
        render: (_: unknown, record) => renderWrappedValue(getSourceService(record)),
      },
      {
        title: "Owning Resource",
        key: "owning_resource",
        width: 260,
        render: (_: unknown, record) => renderWrappedValue(getOwningResource(record)),
      },
      {
        title: "Asset",
        dataIndex: ["asset", "name"],
        width: 220,
        render: (_: unknown, record) => {
          const assetName = record.asset?.name || `Asset #${record.asset_id}`;
          return (
            <Space direction="vertical" size={0} style={{ maxWidth: "100%" }}>
              <Tooltip title={assetName}>
                <Text strong style={wrapTextStyle}>{assetName}</Text>
              </Tooltip>
              <Text type="secondary" style={{ fontSize: 12 }}>
                #{record.asset_id}
              </Text>
            </Space>
          );
        },
      },
      {
        title: "Service",
        dataIndex: ["asset", "service"],
        width: 130,
        render: (_: unknown, record) => record.asset?.service || "-",
      },
      {
        title: "Provider",
        dataIndex: ["asset", "cloud_account", "provider"],
        width: 110,
        render: (_: unknown, record) => {
          const provider = record.asset?.cloud_account?.provider || record.asset?.provider || "";
          return provider ? <Tag color={providerColors[provider.toLowerCase()] || "default"}>{formatProvider(provider)}</Tag> : "-";
        },
      },
      {
        title: "Cloud Account",
        dataIndex: ["asset", "cloud_account", "name"],
        width: 180,
        render: (_: unknown, record) => record.asset?.cloud_account?.name || "-",
      },
      {
        title: "Region",
        dataIndex: ["asset", "region"],
        width: 130,
        render: (_: unknown, record) => record.asset?.region || "-",
      },
      {
        title: "First Seen",
        dataIndex: "first_seen_at",
        width: 160,
        render: (value: string) => formatDate(value),
      },
      {
        title: "Last Seen",
        dataIndex: "last_seen_at",
        width: 160,
        render: (value: string) => formatDate(value),
      },
      {
        title: "Freshness",
        key: "freshness_state",
        width: 130,
        render: (_: unknown, record) => {
          const freshness = getFreshnessState(record);
          return (
            <Tooltip title={freshnessTooltip(record)}>
              <Tag color={freshnessColors[freshness] || "default"}>{freshness.toUpperCase()}</Tag>
            </Tooltip>
          );
        },
      },
    ],
    [],
  );

  return (
    <Space direction="vertical" size={16} style={{ width: "100%" }}>
      <Row align="middle" justify="space-between" gutter={[16, 16]}>
        <Col>
          <Title level={3} style={{ margin: 0 }}>
            IP Assets
          </Title>
        </Col>
        <Col>
          <Button icon={<ReloadOutlined />} onClick={refresh} loading={loading}>
            Refresh
          </Button>
        </Col>
      </Row>

      <Card>
        <Space direction="vertical" size={16} style={{ width: "100%" }}>
          <Row gutter={[12, 12]}>
            <Col xs={24} md={8} lg={7}>
              <Input
                allowClear
                placeholder="Search IP, hostname, or asset"
                value={filters.q}
                onChange={(event) => {
                  setFilters((prev) => ({ ...prev, q: event.target.value }));
                  setPagination((prev) => ({ ...prev, current: 1 }));
                }}
              />
            </Col>
            <Col xs={24} sm={12} md={4}>
              <Select
                allowClear
                placeholder="Exposure"
                options={exposureOptions}
                value={filters.exposure}
                style={{ width: "100%" }}
                onChange={(value) => {
                  setFilters((prev) => ({ ...prev, exposure: value }));
                  setPagination((prev) => ({ ...prev, current: 1 }));
                }}
              />
            </Col>
            <Col xs={24} sm={12} md={4}>
              <Select
                allowClear
                placeholder="Provider"
                options={providerOptions}
                value={filters.provider}
                style={{ width: "100%" }}
                onChange={(value) => {
                  setFilters((prev) => ({ ...prev, provider: value }));
                  setPagination((prev) => ({ ...prev, current: 1 }));
                }}
              />
            </Col>
            <Col xs={24} sm={12} md={4}>
              <Select
                allowClear
                showSearch
                placeholder="Cloud Service"
                options={cloudServiceOptions}
                value={filters.asset_service}
                style={{ width: "100%" }}
                onChange={(value) => {
                  setFilters((prev) => ({ ...prev, asset_service: value }));
                  setPagination((prev) => ({ ...prev, current: 1 }));
                }}
              />
            </Col>
            <Col xs={24} sm={12} md={3}>
              <Input
                allowClear
                placeholder="Region"
                value={filters.region}
                onChange={(event) => {
                  setFilters((prev) => ({ ...prev, region: event.target.value }));
                  setPagination((prev) => ({ ...prev, current: 1 }));
                }}
              />
            </Col>
            <Col xs={24} sm={12} md={5} lg={2}>
              <Button onClick={resetFilters}>Reset</Button>
            </Col>
          </Row>

          <Table<CaasmIPAsset>
            rowKey="id"
            columns={columns}
            dataSource={records}
            loading={loading}
            scroll={{ x: 1960 }}
            locale={{ emptyText: "No IP assets found." }}
            pagination={{
              current: pagination.current,
              pageSize: pagination.pageSize,
              total,
              showSizeChanger: true,
              showTotal: (value) => `${value} IP assets`,
            }}
            onChange={(nextPagination) => setPagination(nextPagination)}
          />
        </Space>
      </Card>
    </Space>
  );
}
