"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { Button, Card, Col, Collapse, Empty, Form, 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 Link from "next/link";
import { useRouter } from "next/navigation";

import { PageStateNotice } from "@/components/common/page-state-notice";
import { fetchVulnerabilities } from "@/lib/api/vulnerabilities";
import { useAuth } from "@/lib/hooks/use-auth";
import type { CriticalityLevel, VulnerabilityListItem, VulnerabilityStatus } from "@/types/models";

const { Title, Paragraph, Text } = Typography;

type FilterState = {
  statuses: VulnerabilityStatus[];
  severities: CriticalityLevel[];
  networkEnv?: string;
  discoveryPhase?: string;
  hasPoc: "all" | "verified" | "unverified";
  overdue: "all" | "overdue" | "on_track";
  thirdParty: "all" | "third_party" | "first_party";
  tags: string[];
  dependencyName?: string;
  batchScope: "all" | "batched" | "single";
  search?: string;
  sortBy: string;
  sortOrder: "asc" | "desc";
};

const MAX_INLINE_TAGS = 3;

const severityColors: Record<CriticalityLevel, string> = {
  critical: "red",
  high: "volcano",
  medium: "gold",
  low: "blue",
};

const statusMeta: Record<VulnerabilityStatus, { label: string; color: string }> = {
  active: { label: "Active", color: "blue" },
  retesting: { label: "Retesting", color: "orange" },
  fixed: { label: "Fixed", color: "green" },
  false_positive: { label: "False Positive", color: "default" },
  risk_accepted: { label: "Risk Accepted", color: "purple" },
};

const terminalStatuses = new Set<VulnerabilityStatus>(["fixed", "false_positive", "risk_accepted"]);

const statusOptions = Object.entries(statusMeta).map(([value, meta]) => ({
  label: meta.label,
  value,
}));

const severityOptions: { label: string; value: CriticalityLevel }[] = [
  { label: "Critical", value: "critical" },
  { label: "High", value: "high" },
  { label: "Medium", value: "medium" },
  { label: "Low", value: "low" },
];

const sortOptions = [
  { label: "Newest submissions", value: "submitted_at:desc" },
  { label: "Oldest submissions", value: "submitted_at:asc" },
  { label: "SLA deadline (soonest)", value: "sla_deadline:asc" },
  { label: "SLA deadline (latest)", value: "sla_deadline:desc" },
  { label: "Severity (high → low)", value: "severity_level:desc" },
];

const networkOptions = [
  { label: "Internal", value: "internal" },
  { label: "External", value: "external" },
];

const discoveryPhaseOptions = [
  { label: "Pre-release", value: "pre_release" },
  { label: "Post-release", value: "post_release" },
];

const pocOptions = [
  { label: "All", value: "all" },
  { label: "Verified", value: "verified" },
  { label: "Not verified", value: "unverified" },
];

const overdueOptions = [
  { label: "All", value: "all" },
  { label: "Overdue only", value: "overdue" },
  { label: "On track", value: "on_track" },
];

const thirdPartyOptions = [
  { label: "All", value: "all" },
  { label: "Third party", value: "third_party" },
  { label: "First party", value: "first_party" },
];

const batchScopeOptions = [
  { label: "All records", value: "all" },
  { label: "Batch only", value: "batched" },
  { label: "Single only", value: "single" },
];

const DEFAULT_VISIBLE_STATUSES: VulnerabilityStatus[] = ["active", "retesting", "fixed"];

const createDefaultFilters = (): FilterState => ({
  statuses: [...DEFAULT_VISIBLE_STATUSES],
  severities: [],
  networkEnv: undefined,
  discoveryPhase: undefined,
  hasPoc: "all",
  overdue: "all",
  thirdParty: "all",
  tags: [],
  dependencyName: "",
  batchScope: "all",
  search: "",
  sortBy: "submitted_at",
  sortOrder: "desc",
});

function displayVulnerabilityID(record: Pick<VulnerabilityListItem, "id" | "public_id">): string {
  return record.public_id?.trim() || `#${record.id}`;
}

function vulnerabilityDetailHref(
  record: Pick<VulnerabilityListItem, "public_id">,
): string | null {
  const publicId = record.public_id?.trim();
  return publicId ? `/dashboard/vulnerabilities/${publicId}` : null;
}

export default function VulnerabilityListPage() {
  const router = useRouter();
  const { hasPermission } = useAuth();
  const canSubmitVulnerability = hasPermission("vuln:submit_findings");
  const [records, setRecords] = useState<VulnerabilityListItem[]>([]);
  const [total, setTotal] = useState(0);
  const [loading, setLoading] = useState(false);
  const [loadError, setLoadError] = useState<string | null>(null);
  const [pagination, setPagination] = useState<TablePaginationConfig>({ current: 1, pageSize: 20 });
  const [filters, setFilters] = useState<FilterState>(() => createDefaultFilters());
  const [searchInput, setSearchInput] = useState(filters.search ?? "");
  const hasActiveFilters = useMemo(
    () =>
      filters.statuses.join(",") !== DEFAULT_VISIBLE_STATUSES.join(",") ||
      filters.severities.length > 0 ||
      Boolean(filters.networkEnv) ||
      Boolean(filters.discoveryPhase) ||
      filters.hasPoc !== "all" ||
      filters.overdue !== "all" ||
      filters.thirdParty !== "all" ||
      filters.tags.length > 0 ||
      Boolean(filters.dependencyName) ||
      filters.batchScope !== "all" ||
      Boolean(filters.search) ||
      filters.sortBy !== "submitted_at" ||
      filters.sortOrder !== "desc",
    [filters],
  );

  const updateFilters = useCallback((next: Partial<FilterState>) => {
    setFilters((prev) => ({
      ...prev,
      ...next,
    }));
    setPagination((prev) => ({ ...prev, current: 1 }));
  }, []);

  const resetFilters = () => {
    setFilters(createDefaultFilters());
    setSearchInput("");
    setPagination((prev) => ({ ...prev, current: 1 }));
  };

  const requestData = useCallback(
    async (page: number, pageSize: number) => {
      setLoading(true);
      try {
        const payload = await fetchVulnerabilities({
          page,
          page_size: pageSize,
          status: filters.statuses.length ? filters.statuses : undefined,
          severity: filters.severities.length ? filters.severities : undefined,
          network_env: filters.networkEnv || undefined,
          discovery_phase: filters.discoveryPhase || undefined,
          has_poc:
            filters.hasPoc === "verified" ? true : filters.hasPoc === "unverified" ? false : undefined,
          is_overdue:
            filters.overdue === "overdue" ? true : filters.overdue === "on_track" ? false : undefined,
          is_third_party:
            filters.thirdParty === "third_party"
              ? true
              : filters.thirdParty === "first_party"
                ? false
                : undefined,
          tags: filters.tags.length ? filters.tags : undefined,
          dependency_name: filters.dependencyName || undefined,
          batch_scope: filters.batchScope,
          search: filters.search || undefined,
          sort_by: filters.sortBy,
          sort_order: filters.sortOrder,
        });
        setRecords(payload.items ?? []);
        setTotal(payload.total ?? 0);
        setLoadError(null);
      } catch (err) {
        console.error("Failed to load vulnerabilities", err);
        setLoadError("The vulnerability inventory could not be loaded right now.");
        setRecords([]);
        setTotal(0);
      } finally {
        setLoading(false);
      }
    },
    [filters],
  );

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

  const handleAction = useCallback(
    (action: string, record: VulnerabilityListItem) => {
      if (action === "view") {
        const href = vulnerabilityDetailHref(record);
        if (!href) {
          message.error("This vulnerability is missing a public ID.");
          return;
        }
        router.push(href);
        return;
      }
      message.info(`Action "${action}" triggered for vulnerability ${displayVulnerabilityID(record)}.`);
    },
    [router],
  );

  const handleAssign = useCallback((record: VulnerabilityListItem) => {
    message.info(`Assign owner from the vulnerability detail page (${displayVulnerabilityID(record)}).`);
  }, []);

  const columns: ColumnsType<VulnerabilityListItem> = useMemo(
    () => [
      {
        title: "ID",
        dataIndex: "public_id",
        key: "public_id",
        width: 140,
        fixed: "left",
        render: (_value: string | undefined, record) => {
          const href = vulnerabilityDetailHref(record);
          if (!href) {
            return <Text strong>{displayVulnerabilityID(record)}</Text>;
          }
          return (
            <Link href={href} prefetch>
              <Text strong>{displayVulnerabilityID(record)}</Text>
            </Link>
          );
        },
      },
      {
        title: "Title",
        dataIndex: "title",
        key: "title",
        width: 260,
        render: (value: string, record) => {
          const href = vulnerabilityDetailHref(record);
          return (
            <Space direction="vertical" size={2}>
              {href ? (
                <Link href={href} prefetch>
                  <Text strong>{value}</Text>
                </Link>
              ) : (
                <Text strong>{value}</Text>
              )}
              {record.tags?.length > 0 && (
                <Space size={4} wrap>
                  {record.tags.slice(0, MAX_INLINE_TAGS).map((tag) => (
                    <Tag key={tag}>{tag}</Tag>
                  ))}
                  {record.tags.length > MAX_INLINE_TAGS && <Tag>+{record.tags.length - MAX_INLINE_TAGS}</Tag>}
                </Space>
              )}
              {record.batch_group_id && (
                <Tooltip title={`Batch group #${record.batch_group_id}`}>
                  <Tag color="purple">Batch #{record.batch_group_id}</Tag>
                </Tooltip>
              )}
            </Space>
          );
        },
      },
      {
        title: "Severity",
        dataIndex: "severity_level",
        key: "severity_level",
        width: 120,
        render: (value: CriticalityLevel) => (
          <Tag color={severityColors[value]} style={{ textTransform: "uppercase" }}>
            {value}
          </Tag>
        ),
      },
      {
        title: "Fix owner",
        key: "owner",
        width: 180,
        render: (_: unknown, record) => (
          <Space direction="vertical" size={2}>
            <Space size={6}>
              <Tooltip title={record.owner_employee?.email ?? "Unassigned"}>
                <Text strong>{record.owner_employee?.name ?? "Unassigned"}</Text>
              </Tooltip>
              <Button
                type="link"
                size="small"
                disabled={!new Set(record.actions ?? []).has("assign_owner")}
                onClick={() => handleAssign(record)}
              >
                Assign
              </Button>
            </Space>
            {record.owner_employee?.email && (
              <Text type="secondary" style={{ fontSize: 12 }}>
                {record.owner_employee.email}
              </Text>
            )}
          </Space>
        ),
      },
      {
        title: "Submitter",
        key: "submitter",
        width: 160,
        render: (_: unknown, record) => (
          <Space direction="vertical" size={0}>
            <Tooltip title={record.submitter?.email ?? "—"}>
              <Text strong>{record.submitter?.name ?? "—"}</Text>
            </Tooltip>
            <Text type="secondary" style={{ fontSize: 12 }}>
              {record.submitter?.email ?? "—"}
            </Text>
          </Space>
        ),
      },
      {
        title: "Affected assets",
        dataIndex: "affected_assets_count",
        key: "assets",
        width: 110,
        render: (value: number) => value ?? 0,
      },
      {
        title: "Business department",
        key: "department",
        width: 150,
        render: (_: unknown, record) =>
          record.department?.name ?? record.department_id ?? "—",
      },
      {
        title: "Source",
        dataIndex: "source",
        key: "source",
        width: 140,
        render: (value: string) => value || "—",
      },
      {
        title: "Status",
        dataIndex: "status",
        key: "status",
        width: 140,
        render: (value: VulnerabilityStatus) => (
          <Tag color={statusMeta[value].color}>{statusMeta[value].label}</Tag>
        ),
      },
      {
        title: "Discovery phase",
        dataIndex: "discovery_phase",
        key: "discovery_phase",
        width: 150,
        render: (value: string) => value || "—",
      },
      {
        title: "Network environment",
        dataIndex: "network_env",
        key: "network_env",
        width: 170,
        render: (value: string) => value || "—",
      },
      {
        title: "Submitted",
        dataIndex: "submitted_at",
        key: "submitted_at",
        width: 180,
        render: (value: string) => (value ? dayjs(value).format("YYYY-MM-DD HH:mm") : "—"),
      },
      {
        title: "Actions",
        key: "actions",
        fixed: "right",
        width: 160,
        render: (_: unknown, record) => {
          const available = new Set(record.actions ?? []);
          const canView = !record.actions || available.has("view");
          const canAssign = available.has("assign_owner");
          return (
            <Space>
              <Button type="link" size="small" disabled={!canView} onClick={() => handleAction("view", record)}>
                View
              </Button>
              <Button size="small" disabled={!canAssign} onClick={() => handleAssign(record)}>
                Assign
              </Button>
            </Space>
          );
        },
      },
    ],
    [handleAction, handleAssign],
  );

  return (
    <Space direction="vertical" size={24} style={{ width: "100%" }}>
      <Space align="baseline" style={{ justifyContent: "space-between", width: "100%" }}>
        <div>
          <Title level={3} style={{ marginBottom: 4 }}>
            Vulnerability List
          </Title>
          <Paragraph type="secondary" style={{ margin: 0 }}>
            Monitor remediation status, SLA health, and ownership across all tracked vulnerabilities.
          </Paragraph>
        </div>
        <Space>
          <Button type="link" href="/dashboard/vulnerabilities/search">
            Advanced search
          </Button>
          <Button
            icon={<ReloadOutlined />}
            onClick={() => requestData(pagination.current ?? 1, pagination.pageSize ?? 20)}
            disabled={loading}
          >
            Refresh
          </Button>
        </Space>
      </Space>

      <Card>
        <Form layout="vertical">
          <Row gutter={[16, 16]}>
            <Col xs={24} md={12} lg={6}>
              <Form.Item label="Status">
                <Select
                  mode="multiple"
                  value={filters.statuses}
                  placeholder="Select statuses"
                  options={statusOptions}
                  onChange={(value) => updateFilters({ statuses: value as VulnerabilityStatus[] })}
                />
              </Form.Item>
            </Col>
            <Col xs={24} md={12} lg={6}>
              <Form.Item label="Severity">
                <Select
                  mode="multiple"
                  placeholder="All severities"
                  value={filters.severities}
                  options={severityOptions}
                  onChange={(value) => updateFilters({ severities: value as CriticalityLevel[] })}
                />
              </Form.Item>
            </Col>
            <Col xs={24} md={12} lg={6}>
              <Form.Item label="Keyword search">
                <Input.Search
                  allowClear
                  placeholder="Title, dependency, description..."
                  value={searchInput}
                  onChange={(event) => setSearchInput(event.target.value)}
                  onSearch={(value) => updateFilters({ search: value || undefined })}
                />
              </Form.Item>
            </Col>
            <Col xs={24} md={12} lg={6}>
              <Form.Item label="Sort by">
                <Select
                  value={`${filters.sortBy}:${filters.sortOrder}`}
                  options={sortOptions}
                  onChange={(value) => {
                    const [sortBy, sortOrder] = value.split(":");
                    updateFilters({
                      sortBy,
                      sortOrder: (sortOrder === "asc" ? "asc" : "desc") as FilterState["sortOrder"],
                    });
                  }}
                />
              </Form.Item>
            </Col>
          </Row>
          <Collapse
            bordered={false}
            items={[
              {
                key: "advanced",
                label: "Advanced filters",
                children: (
                  <Row gutter={[16, 16]}>
                    <Col xs={24} md={12} lg={6}>
                      <Form.Item label="Network environment">
                        <Select
                          allowClear
                          placeholder="Any"
                          value={filters.networkEnv}
                          options={networkOptions}
                          onChange={(value) => updateFilters({ networkEnv: value ?? undefined })}
                        />
                      </Form.Item>
                    </Col>
                    <Col xs={24} md={12} lg={6}>
                      <Form.Item label="Discovery phase">
                        <Select
                          allowClear
                          placeholder="Any"
                          value={filters.discoveryPhase}
                          options={discoveryPhaseOptions}
                          onChange={(value) => updateFilters({ discoveryPhase: value ?? undefined })}
                        />
                      </Form.Item>
                    </Col>
                    <Col xs={24} md={12} lg={6}>
                      <Form.Item label="POC verification">
                        <Select
                          value={filters.hasPoc}
                          options={pocOptions}
                          onChange={(value) => updateFilters({ hasPoc: value as FilterState["hasPoc"] })}
                        />
                      </Form.Item>
                    </Col>
                    <Col xs={24} md={12} lg={6}>
                      <Form.Item label="SLA health">
                        <Select
                          value={filters.overdue}
                          options={overdueOptions}
                          onChange={(value) => updateFilters({ overdue: value as FilterState["overdue"] })}
                        />
                      </Form.Item>
                    </Col>
                    <Col xs={24} md={12} lg={6}>
                      <Form.Item label="Third-party">
                        <Select
                          value={filters.thirdParty}
                          options={thirdPartyOptions}
                          onChange={(value) => updateFilters({ thirdParty: value as FilterState["thirdParty"] })}
                        />
                      </Form.Item>
                    </Col>
                    <Col xs={24} md={12} lg={6}>
                      <Form.Item label="Tags">
                        <Select
                          mode="tags"
                          placeholder="Add or search tags"
                          value={filters.tags}
                          onChange={(value) => updateFilters({ tags: value })}
                          tokenSeparators={[","]}
                        />
                      </Form.Item>
                    </Col>
                    <Col xs={24} md={12} lg={6}>
                      <Form.Item label="Dependency name">
                        <Input
                          allowClear
                          placeholder="e.g., log4j-core"
                          value={filters.dependencyName}
                          onChange={(event) => updateFilters({ dependencyName: event.target.value })}
                        />
                      </Form.Item>
                    </Col>
                    <Col xs={24} md={12} lg={6}>
                      <Form.Item label="Batch scope">
                        <Select
                          value={filters.batchScope}
                          options={batchScopeOptions}
                          onChange={(value) => updateFilters({ batchScope: value as FilterState["batchScope"] })}
                        />
                      </Form.Item>
                    </Col>
                  </Row>
                ),
              },
            ]}
          />
          <Row justify="space-between" align="middle" style={{ marginTop: 16 }}>
            <Col>
              <Button type="default" onClick={resetFilters}>
                Reset filters
              </Button>
            </Col>
            <Col>
              <Button type="link" href="/dashboard/vulnerabilities/search">
                Open advanced search
              </Button>
            </Col>
          </Row>
        </Form>
      </Card>

      {canSubmitVulnerability ? (
        <Row justify="start">
          <Button type="primary" onClick={() => router.push("/dashboard/vulnerabilities/submit")}>
            Submit Vulnerability
          </Button>
        </Row>
      ) : null}

      <Card>
        <Table<VulnerabilityListItem>
          rowKey={(record) => String(record.id)}
          columns={columns}
          dataSource={records}
          loading={loading}
          locale={{
            emptyText: loadError ? (
              <PageStateNotice
                tone="error"
                compact
                title="Vulnerability inventory unavailable"
                description={`${loadError} Retry the list or use the submission flow if you need to capture a new issue manually.`}
                actions={
                  <Space wrap>
                    <Button icon={<ReloadOutlined />} onClick={() => requestData(pagination.current ?? 1, pagination.pageSize ?? 20)}>
                      Retry list
                    </Button>
                    {canSubmitVulnerability ? (
                      <Button type="primary" onClick={() => router.push("/dashboard/vulnerabilities/submit")}>
                        Submit vulnerability
                      </Button>
                    ) : null}
                  </Space>
                }
              />
            ) : hasActiveFilters ? (
              <PageStateNotice
                tone="empty"
                compact
                title="No vulnerabilities match the current filters"
                description="Clear or adjust the filters to reveal matching findings, or submit a new vulnerability if you already know about one."
                actions={
                  <Space wrap>
                    {canSubmitVulnerability ? (
                      <Button type="primary" onClick={() => router.push("/dashboard/vulnerabilities/submit")}>
                        Submit vulnerability
                      </Button>
                    ) : null}
                    <Button onClick={resetFilters}>Reset filters</Button>
                  </Space>
                }
              />
            ) : (
              <PageStateNotice
                tone="empty"
                compact
                title="No vulnerabilities have been submitted yet"
                description="Submit the first vulnerability to start tracking ownership, SLA progress, and remediation status in one place."
                actions={
                  <Space wrap>
                    {canSubmitVulnerability ? (
                      <Button type="primary" onClick={() => router.push("/dashboard/vulnerabilities/submit")}>
                        Submit vulnerability
                      </Button>
                    ) : null}
                    <Button type="link" href="/dashboard/vulnerabilities/search">
                      Open advanced search
                    </Button>
                  </Space>
                }
              />
            ),
          }}
          pagination={{
            ...pagination,
            total,
            showSizeChanger: true,
          }}
          scroll={{ x: 1400 }}
          onChange={(pager: TablePaginationConfig) => {
            setPagination((prev) => ({
              ...prev,
              current: pager.current ?? prev.current ?? 1,
              pageSize: pager.pageSize ?? prev.pageSize ?? 20,
            }));
          }}
        />
      </Card>
    </Space>
  );
}

function getRemainingLabel(record: VulnerabilityListItem): string | null {
  if (!record.sla_deadline || terminalStatuses.has(record.status)) {
    return null;
  }
  const deadline = dayjs(record.sla_deadline);
  if (!deadline.isValid()) {
    return null;
  }
  const now = dayjs();
  const diffMs = deadline.diff(now);
  const durationText = formatDuration(Math.abs(diffMs));
  if (!durationText) {
    return null;
  }
  return diffMs >= 0 ? `Remaining ${durationText}` : `Overdue ${durationText}`;
}

function formatDuration(ms: number): string {
  if (!Number.isFinite(ms) || ms <= 0) {
    return "";
  }
  const totalMinutes = Math.floor(ms / (1000 * 60));
  if (totalMinutes <= 0) {
    return "<1m";
  }
  const days = Math.floor(totalMinutes / (60 * 24));
  const hours = Math.floor((totalMinutes - days * 60 * 24) / 60);
  const minutes = totalMinutes % 60;
  const parts: string[] = [];
  if (days) parts.push(`${days}d`);
  if (hours) parts.push(`${hours}h`);
  if (!days && minutes) parts.push(`${minutes}m`);
  if (!parts.length) {
    parts.push("<1m");
  }
  return parts.join(" ");
}
