"use client";

import type { Brand, Region } from "@domainops/shared-types";
import { App, Button, Input, Popconfirm, Select, Table, Tag, Tooltip, Typography } from "antd";
import { DeleteOutlined, EditOutlined, HolderOutlined, PlusOutlined } from "@ant-design/icons";
import type { ColumnsType } from "antd/es/table";
import Link from "next/link";
import { useCallback, useEffect, useState } from "react";
import { useRowDragReorder } from "@/lib/hooks/useRowDragReorder";
import { archiveBrand, listBrands, listRegions, reorderBrands, resetBrandOrder } from "@/lib/api/domains";
import { ApiError } from "@/lib/api/client";
import { PageGuide } from "@/components/features/PageGuide";
import { PROJECTS_GUIDES } from "@/lib/guides/domains";
import { BrandFormModal } from "./BrandFormModal";

/**
 * Brands list A-Z by default (the Name column also sorts Z-A). Any row can be
 * dragged to a new position: dropping it saves that order, and it then applies
 * to every brand dropdown in the app until "Reset to A-Z" is used. Dragging is
 * paused while a search or region filter is active.
 */
export default function BrandsPage() {
  const { message, modal } = App.useApp();
  const [brands, setBrands] = useState<Brand[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [editingBrand, setEditingBrand] = useState<Brand | null>(null);
  const [selectedIds, setSelectedIds] = useState<number[]>([]);
  const [isBulkWorking, setIsBulkWorking] = useState(false);
  const [regions, setRegions] = useState<Region[]>([]);
  const [search, setSearch] = useState("");
  const [regionId, setRegionId] = useState<number | undefined>();
  const [isCustomOrder, setIsCustomOrder] = useState(false);
  const [nameOrder, setNameOrder] = useState<"ascend" | "descend">("ascend");
  const isFiltering = search.trim() !== "" || regionId !== undefined;

  const filtered = brands.filter(
    (b) =>
      b.name.toLowerCase().includes(search.trim().toLowerCase()) &&
      (regionId === undefined || (b.regions ?? []).some((r) => r.id === regionId)),
  );
  const visibleBrands = isCustomOrder
    ? filtered
    : [...filtered].sort((a, b) => (nameOrder === "ascend" ? 1 : -1) * a.name.localeCompare(b.name));

  const load = useCallback(async () => {
    setIsLoading(true);
    try {
      const result = await listBrands();
      setBrands(result);
      setIsCustomOrder(result[0]?.order_mode === "custom");
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't load projects.");
    } finally {
      setIsLoading(false);
    }
  }, [message]);

  useEffect(() => {
    // Server data lives on the Laravel API, not in Next's own data layer -
    // a client fetch on mount, not a state-sync bug.
    // eslint-disable-next-line react-hooks/set-state-in-effect
    void load();
    void listRegions().then(setRegions);
  }, [load]);

  async function handleArchive(brand: Brand) {
    try {
      await archiveBrand(brand.id);
      message.success(`${brand.name} archived.`);
      void load();
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't archive that project.");
    }
  }

  async function handleReorder(ids: number[]) {
    const byId = new Map(brands.map((b) => [b.id, b]));
    setBrands(ids.map((id) => byId.get(id)!));
    setIsCustomOrder(true);

    try {
      setBrands(await reorderBrands(ids));
      message.success("Project order saved.");
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't save that order.");
      void load();
    }
  }

  function handleResetOrder() {
    modal.confirm({
      title: "Go back to A-Z order?",
      content: "Your custom order is replaced everywhere projects are listed.",
      okText: "Use A-Z",
      onOk: async () => {
        try {
          setBrands(await resetBrandOrder());
          setIsCustomOrder(false);
          setNameOrder("ascend");
        } catch (err) {
          message.error(err instanceof ApiError ? err.message : "Couldn't reset the order.");
        }
      },
    });
  }

  async function handleBulkArchive() {
    const targets = brands.filter((b) => selectedIds.includes(b.id));
    setIsBulkWorking(true);
    try {
      const results = await Promise.allSettled(targets.map((b) => archiveBrand(b.id)));
      const succeeded = results.filter((r) => r.status === "fulfilled").length;
      const failed = results.length - succeeded;
      if (succeeded > 0) message.success(`Archived ${succeeded} project${succeeded === 1 ? "" : "s"}.`);
      if (failed > 0) message.error(`Failed for ${failed} project${failed === 1 ? "" : "s"}.`);
      setSelectedIds([]);
      void load();
    } finally {
      setIsBulkWorking(false);
    }
  }

  const { onRow } = useRowDragReorder<Brand>({ items: visibleBrands, enabled: !isFiltering, onReorder: handleReorder });

  const columns: ColumnsType<Brand> = [
    {
      title: "",
      width: 48,
      render: () => (
        <Tooltip title={isFiltering ? "Clear the search or filter to reorder" : "Drag to reorder"}>
          <HolderOutlined style={{ cursor: isFiltering ? "not-allowed" : "grab", fontSize: 18, opacity: isFiltering ? 0.35 : 1 }} className="dms_brands_drag_handle" />
        </Tooltip>
      ),
    },
    {
      title: "Name",
      dataIndex: "name",
      sorter: isCustomOrder ? undefined : true,
      sortOrder: isCustomOrder ? undefined : nameOrder,
      sortDirections: ["ascend", "descend"],
      render: (v: string) => <span className="font-semibold">{v}</span>,
    },
    {
      title: "Regions",
      dataIndex: "regions",
      render: (regions: Brand["regions"]) => (
        <span className="flex gap-1 flex-wrap">
          {regions?.length ? regions.map((r) => <Tag key={r.id}>{r.country_code}</Tag>) : "—"}
        </span>
      ),
    },
    {
      title: "Brands",
      dataIndex: "project_brands",
      render: (items: Brand["project_brands"]) => (
        <span className="flex gap-1 flex-wrap">{items?.length ? items.map((b) => <Tag key={b.id}>{b.name}</Tag>) : "—"}</span>
      ),
    },
    {
      title: "Keywords",
      dataIndex: "keywords",
      render: (items: Brand["keywords"]) => (
        <span className="flex gap-1 flex-wrap">{items?.length ? items.map((k) => <Tag key={k.id} color="blue">{k.keyword}</Tag>) : "—"}</span>
      ),
    },
    {
      title: "Domains",
      dataIndex: "domains_count",
      render: (v: number | undefined, brand) => (
        <Link href={`/domains?brand_id=${brand.id}`} className="dms_brands_domains_link">
          {v ?? 0}
        </Link>
      ),
    },
    {
      title: "Actions",
      render: (_, brand) => (
        <div className="flex gap-2">
          <Tooltip title="Edit">
            <Button
              size="small"
              icon={<EditOutlined />}
              onClick={() => {
                setEditingBrand(brand);
                setIsModalOpen(true);
              }}
              className="dms_brands_edit_btn"
            />
          </Tooltip>
          <Popconfirm title={`Archive ${brand.name}?`} onConfirm={() => handleArchive(brand)}>
            <Tooltip title="Archive">
              <Button size="small" danger icon={<DeleteOutlined />} className="dms_brands_archive_btn" />
            </Tooltip>
          </Popconfirm>
        </div>
      ),
    },
  ];

  return (
    <div className="flex flex-col gap-4 page page-brands">
      <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 }}>
            Projects
          </Typography.Title>
          <PageGuide guides={PROJECTS_GUIDES} label="Projects guide" />
        </div>
        <div className="flex items-center gap-4">
          {isCustomOrder ? (
            <Button onClick={handleResetOrder} className="dms_brands_reset_order_btn">
              Reset to A-Z
            </Button>
          ) : (
            <Typography.Text type="secondary">Drag rows to set a custom order</Typography.Text>
          )}
          <Button
            type="primary"
            icon={<PlusOutlined />}
            onClick={() => {
              setEditingBrand(null);
              setIsModalOpen(true);
            }}
            className="dms_brands_create_btn"
          >
            Create project
          </Button>
        </div>
      </div>

      <div className="flex gap-2 flex-wrap dms_brands_filters">
        <Input.Search
          allowClear
          placeholder="Search projects"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          style={{ width: 260 }}
          className="dms_brands_search_input"
        />
        <Select<number>
          allowClear
          showSearch
          optionFilterProp="label"
          placeholder="Filter by region"
          value={regionId}
          onChange={setRegionId}
          options={regions.map((r) => ({ value: r.id, label: `${r.name} (${r.country_code})` }))}
          style={{ width: 220 }}
          className="dms_brands_region_filter"
        />
      </div>

      {selectedIds.length > 0 && (
        <div className="flex items-center gap-2 flex-wrap dms_brands_bulk_bar">
          <Typography.Text>{selectedIds.length} selected</Typography.Text>
          <Popconfirm title="Archive the selected projects?" onConfirm={handleBulkArchive}>
            <Button size="small" danger icon={<DeleteOutlined />} loading={isBulkWorking} className="dms_brands_bulk_archive_btn">
              Archive
            </Button>
          </Popconfirm>
          <Button size="small" onClick={() => setSelectedIds([])} className="dms_brands_bulk_clear_btn">
            Clear
          </Button>
        </div>
      )}

      <Table<Brand>
        rowKey="id"
        columns={columns}
        dataSource={visibleBrands}
        loading={isLoading}
        rowSelection={{
          selectedRowKeys: selectedIds,
          onChange: (keys) => setSelectedIds(keys as number[]),
        }}
        onChange={(_pagination, _filters, sorter) => {
          const active = Array.isArray(sorter) ? sorter[0] : sorter;
          setNameOrder(active?.order === "descend" ? "descend" : "ascend");
        }}
        onRow={onRow}
        pagination={false}
        className="dms_brands_table"
      />

      <BrandFormModal
        open={isModalOpen}
        brand={editingBrand}
        onClose={() => setIsModalOpen(false)}
        onSaved={() => {
          setIsModalOpen(false);
          void load();
        }}
      />
    </div>
  );
}
