"use client";

import type { Brand, BulkDomainFilters, CloudflareAccount, Region, RegistrarAccount, ServerAccount } from "@domainops/shared-types";
import { App, Button, Modal, Select } from "antd";
import { PlusOutlined } from "@ant-design/icons";
import { useEffect, useState } from "react";
import type { BulkAssignChanges } from "@/lib/api/domains";
import { bulkAssignField, listRegions } from "@/lib/api/domains";
import { listRegistrars } from "@/lib/api/acquire";
import { listCloudflareAccounts } from "@/lib/api/cloudflare";
import { listServerAccounts } from "@/lib/api/servers";
import { ApiError } from "@/lib/api/client";
import { PURPOSE_OPTIONS } from "@/lib/utils/domainFields";
import { serverAccountLabel } from "@/lib/utils/server";
import { BrandFormModal } from "./brands/BrandFormModal";
import { QuickServerAccountModal } from "./QuickServerAccountModal";

/**
 * One bulk-assign popup for the whole selection: Registrar, Brand,
 * Cloudflare, Server, Region and Purpose can all be set in a single save.
 * A field left empty is not changed. Brand and Server Account can also be
 * created on the spot, so a selection can move to something that does not
 * exist yet in the same flow.
 */
export function BulkAssignBar({
  selectedIds,
  filters,
  totalFiltered,
  brands,
  onDone,
  onBrandCreated,
}: {
  selectedIds: number[];
  filters: BulkDomainFilters;
  totalFiltered: number;
  brands: Brand[];
  onDone: () => void;
  onBrandCreated?: () => void;
}) {
  const { message } = App.useApp();
  const [isOpen, setIsOpen] = useState(false);
  const [changes, setChanges] = useState<BulkAssignChanges>({});
  const [registrars, setRegistrars] = useState<RegistrarAccount[]>([]);
  const [regions, setRegions] = useState<Region[]>([]);
  const [cloudflareAccounts, setCloudflareAccounts] = useState<CloudflareAccount[]>([]);
  const [serverAccounts, setServerAccounts] = useState<ServerAccount[]>([]);
  const [createdBrands, setCreatedBrands] = useState<Brand[]>([]);
  const [isBrandModalOpen, setIsBrandModalOpen] = useState(false);
  const [isServerModalOpen, setIsServerModalOpen] = useState(false);
  const [isBusy, setIsBusy] = useState(false);

  useEffect(() => {
    if (!isOpen) return;
    void listRegistrars().then((result) => setRegistrars(result.accounts));
    void listRegions().then(setRegions);
    void listCloudflareAccounts().then(setCloudflareAccounts);
    void listServerAccounts().then(setServerAccounts);
  }, [isOpen]);

  const hasSelection = selectedIds.length > 0;
  const canRun = hasSelection || Object.values(filters).some((v) => v !== undefined && v !== "");
  const scopeLabel = hasSelection ? `${selectedIds.length} selected` : `all ${totalFiltered} matching the filter`;
  const allBrands = [...brands, ...createdBrands.filter((c) => !brands.some((b) => b.id === c.id))];
  const changeCount = Object.values(changes).filter((v) => v !== undefined).length;

  function setChange<K extends keyof BulkAssignChanges>(key: K, value: BulkAssignChanges[K] | undefined) {
    setChanges((current) => ({ ...current, [key]: value }));
  }

  async function handleAssign() {
    if (changeCount === 0) return;
    setIsBusy(true);
    try {
      const result = await bulkAssignField(hasSelection ? { domain_ids: selectedIds, changes } : { filters, changes });
      message.success(`${result.updated} domain(s) updated.`);
      setIsOpen(false);
      setChanges({});
      onDone();
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't apply those changes.");
    } finally {
      setIsBusy(false);
    }
  }

  return (
    <>
      <Button disabled={!canRun} onClick={() => setIsOpen(true)} className="bulk-assign-bar dms_bulk_assign_open_btn">
        Bulk Assign ({scopeLabel})
      </Button>

      <Modal
        title="Bulk Assign"
        open={isOpen}
        onCancel={() => setIsOpen(false)}
        onOk={handleAssign}
        okText={changeCount > 0 ? `Apply ${changeCount} change${changeCount === 1 ? "" : "s"}` : "Apply"}
        okButtonProps={{ disabled: changeCount === 0, loading: isBusy }}
        destroyOnHidden
        className="dms_bulk_assign_modal"
      >
        <p>
          Applies to {scopeLabel}. Set as many fields as you like - anything left empty stays as it is.
        </p>
        <div className="flex flex-col gap-3 dms_bulk_assign_form">
          <Select<number>
            allowClear
            showSearch
            optionFilterProp="label"
            placeholder="Registrar - no change"
            value={changes.registrar_account_id}
            onChange={(v) => setChange("registrar_account_id", v)}
            options={registrars.map((r) => ({ value: r.id, label: r.label }))}
            className="w-full dms_bulk_assign_registrar_select"
          />
          <Select<number>
            allowClear
            showSearch
            optionFilterProp="label"
            placeholder="Project - no change"
            value={changes.brand_id}
            onChange={(v) => setChange("brand_id", v)}
            options={allBrands.map((b) => ({ value: b.id, label: b.name }))}
            className="w-full dms_bulk_assign_brand_select"
          />
          <Button icon={<PlusOutlined />} onClick={() => setIsBrandModalOpen(true)} className="dms_bulk_assign_new_brand_btn">
            Create a new project and assign to it
          </Button>
          <Select<number>
            allowClear
            showSearch
            optionFilterProp="label"
            placeholder="Cloudflare account - no change"
            value={changes.cf_account_id}
            onChange={(v) => setChange("cf_account_id", v)}
            options={cloudflareAccounts.map((a) => ({ value: a.id, label: a.label }))}
            className="w-full dms_bulk_assign_cloudflare_select"
          />
          <Select<number>
            allowClear
            showSearch
            optionFilterProp="label"
            placeholder="Server account - no change"
            value={changes.server_account_id}
            onChange={(v) => setChange("server_account_id", v)}
            options={serverAccounts.map((a) => ({ value: a.id, label: serverAccountLabel(a) }))}
            className="w-full dms_bulk_assign_server_select"
          />
          <Button icon={<PlusOutlined />} onClick={() => setIsServerModalOpen(true)} className="dms_bulk_assign_new_server_btn">
            Add a new server account and assign to it
          </Button>
          <Select<number>
            allowClear
            showSearch
            optionFilterProp="label"
            placeholder="Region - no change"
            value={changes.region_id}
            onChange={(v) => setChange("region_id", v)}
            options={regions.map((r) => ({ value: r.id, label: `${r.name} (${r.country_code})` }))}
            className="w-full dms_bulk_assign_region_select"
          />
          <Select
            allowClear
            placeholder="Purpose - no change"
            value={changes.purpose}
            onChange={(v) => setChange("purpose", v)}
            options={PURPOSE_OPTIONS}
            className="w-full dms_bulk_assign_purpose_select"
          />
        </div>
      </Modal>

      <BrandFormModal
        open={isBrandModalOpen}
        onClose={() => setIsBrandModalOpen(false)}
        onSaved={(brand) => {
          setIsBrandModalOpen(false);
          setCreatedBrands((current) => [...current, brand]);
          setChange("brand_id", brand.id);
          onBrandCreated?.();
        }}
      />
      <QuickServerAccountModal
        open={isServerModalOpen}
        onClose={() => setIsServerModalOpen(false)}
        onCreated={(account) => {
          setIsServerModalOpen(false);
          setServerAccounts((current) => [...current, account]);
          setChange("server_account_id", account.id);
        }}
      />
    </>
  );
}
