"use client";

import type { Brand, RedirectGraph, RedirectGraphNode } from "@domainops/shared-types";
import { App, Button, Card, Empty, Popconfirm, Select, Tag, Typography } from "antd";
import Link from "next/link";
import { useCallback, useEffect, useState } from "react";
import { breakLoop, flattenChain, getRedirectGraph } from "@/lib/api/redirects";
import { listBrands } from "@/lib/api/domains";
import { ApiError } from "@/lib/api/client";
import { PageGuide } from "@/components/features/PageGuide";
import { REDIRECT_MAP_GUIDES } from "@/lib/guides/redirects";
import { NodeHistoryDrawer } from "./NodeHistoryDrawer";
import { RedirectMapSvg } from "./RedirectMapSvg";

function fqdnOf(graph: RedirectGraph | null, id: number): string {
  return graph?.nodes.find((n) => n.id === id)?.fqdn ?? `#${id}`;
}

export default function RedirectMapPage() {
  const { message } = App.useApp();
  const [graph, setGraph] = useState<RedirectGraph | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [brands, setBrands] = useState<Brand[]>([]);
  const [brandId, setBrandId] = useState<number | undefined>();
  const [selectedNode, setSelectedNode] = useState<RedirectGraphNode | null>(null);

  const load = useCallback(async () => {
    setIsLoading(true);
    try {
      setGraph(await getRedirectGraph({ brand_id: brandId }));
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't load the redirect map.");
    } finally {
      setIsLoading(false);
    }
  }, [brandId, message]);

  useEffect(() => {
    // eslint-disable-next-line react-hooks/set-state-in-effect
    void load();
  }, [load]);

  useEffect(() => {
    void listBrands().then(setBrands);
  }, []);

  async function handleFlatten(domainId: number) {
    try {
      await flattenChain(domainId);
      message.success("Chain flattened.");
      void load();
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't flatten that chain.");
    }
  }

  async function handleBreakLoop(domainId: number) {
    try {
      await breakLoop(domainId);
      message.success("Loop broken.");
      void load();
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't break that loop.");
    }
  }

  function selectNode(nodeId: number) {
    const node = graph?.nodes.find((n) => n.id === nodeId) ?? null;
    setSelectedNode(node);
  }

  const hasProblems =
    !!graph &&
    (graph.chains.length > 0 ||
      graph.loops.length > 0 ||
      graph.flagged_targets.length > 0 ||
      graph.direction_flips.length > 0);

  return (
    <div className="flex flex-col gap-4 page page-redirect-map">
      <div className="flex items-center justify-between flex-wrap gap-2">
        <div className="flex items-center gap-2">
          <Typography.Title level={4} style={{ margin: 0 }}>
            Redirect map
          </Typography.Title>
          <PageGuide guides={REDIRECT_MAP_GUIDES} label="Redirect map guide" />
        </div>
        <Link href="/redirects">
          <Button className="dms_redirects_map_back_to_list_btn">Back to list</Button>
        </Link>
      </div>

      <Card title="Filter" className="redirect-map__filters dms_redirects_map_filter_card">
        <div className="flex items-center gap-3 flex-wrap">
          <Select
            allowClear
            placeholder="Project"
            style={{ width: 200 }}
            value={brandId}
            options={brands.map((b) => ({ value: b.id, label: b.name }))}
            onChange={(value) => setBrandId(value)}
            className="dms_redirects_map_brand_select"
          />
        </div>
      </Card>

      {hasProblems && (
        <Card title="Problems Detected" className="redirect-map__problems dms_redirects_map_problems_card">
          <div className="flex flex-col gap-2">
            {graph!.chains.map((chain, i) => (
              <div key={`chain-${i}`} className="flex items-center gap-2 flex-wrap">
                <Tag color="orange">Chain</Tag>
                <span className="font-mono text-xs">
                  {chain.map((id) => fqdnOf(graph, id)).join(" → ")}
                </span>
                <Popconfirm
                  title="Flatten this chain?"
                  description={`Repoints ${fqdnOf(graph, chain[0])} directly at the final target.`}
                  onConfirm={() => void handleFlatten(chain[0])}
                >
                  <Button size="small" className="dms_redirects_map_flatten_chain_btn">Flatten</Button>
                </Popconfirm>
              </div>
            ))}

            {graph!.loops.map((loop, i) => (
              <div key={`loop-${i}`} className="flex items-center gap-2 flex-wrap">
                <Tag color="red">Loop</Tag>
                <span className="font-mono text-xs">{loop.map((id) => fqdnOf(graph, id)).join(" ⇄ ")}</span>
                <Popconfirm
                  title="Break this loop?"
                  description={`Removes ${fqdnOf(graph, loop[0])}'s redirect to break the cycle.`}
                  onConfirm={() => void handleBreakLoop(loop[0])}
                >
                  <Button size="small" danger className="dms_redirects_map_break_loop_btn">
                    Break loop
                  </Button>
                </Popconfirm>
              </div>
            ))}

            {graph!.flagged_targets.map((f, i) => (
              <div key={`flag-${i}`} className="flex items-center gap-2 flex-wrap">
                <Tag color="gold">Flagged ({f.reason})</Tag>
                <span className="font-mono text-xs">
                  {fqdnOf(graph, f.source_domain_id)} → {fqdnOf(graph, f.target_domain_id)}
                </span>
              </div>
            ))}

            {graph!.direction_flips.map((f, i) => (
              <div key={`flip-${i}`} className="flex items-center gap-2 flex-wrap">
                <Tag color="purple">Direction flip</Tag>
                <span className="font-mono text-xs">
                  {fqdnOf(graph, f.source_domain_id)} → {fqdnOf(graph, f.target_domain_id)} (previously reversed)
                </span>
              </div>
            ))}
          </div>
        </Card>
      )}

      <Card title="Map" loading={isLoading} className="redirect-map__canvas dms_redirects_map_canvas_card">
        {graph && graph.nodes.length > 0 ? (
          <RedirectMapSvg graph={graph} onSelectNode={selectNode} />
        ) : (
          !isLoading && <Empty description="No domains to map yet." />
        )}
      </Card>

      <NodeHistoryDrawer node={selectedNode} onClose={() => setSelectedNode(null)} />
    </div>
  );
}
