"use client";

import type {
  CloudflareAccount,
  CloudflareProvisionStep,
  Domain,
  DomainPurpose,
  ServerAccount,
  ServerGroup,
} from "@domainops/shared-types";
import { App, Button, Card, Checkbox, Form, Select, Table, Tag } from "antd";
import { useEffect, useState } from "react";
import { provisionServer, updateDomain } from "@/lib/api/domains";
import { createSecurityRule, listCloudflareAccounts, provisionCloudflare } from "@/lib/api/cloudflare";
import { listServerAccounts, listServerGroups } from "@/lib/api/servers";
import { buildServerOptions, resolveServerAccountId } from "@/lib/utils/serverChoice";
import { ApiError } from "@/lib/api/client";

const PURPOSE_OPTIONS: { value: DomainPurpose; label: string }[] = [
  { value: "html", label: "HTML site (zip upload)" },
  { value: "wordpress", label: "WordPress" },
  { value: "redirect", label: "301 redirect" },
  { value: "other", label: "Other" },
];

// Built with the existing per-zone security-rule mechanism - not a
// distinct Cloudflare capability. Kept modest and labeled as a starting
// point, not a comprehensive WAF.
const AI_BOT_RULE = {
  description: "Block known AI crawlers",
  expression:
    '(http.user_agent contains "GPTBot") or (http.user_agent contains "CCBot") or (http.user_agent contains "ClaudeBot") or (http.user_agent contains "Bytespider") or (http.user_agent contains "Google-Extended")',
  action: "block" as const,
};

const WAF_PRESET_RULES = [
  { description: "Block empty user agent", expression: '(http.user_agent eq "")', action: "block" as const },
  {
    description: "Challenge known scraper tools",
    expression: '(http.user_agent contains "python-requests") or (http.user_agent contains "curl") or (http.user_agent contains "Scrapy")',
    action: "challenge" as const,
  },
];

interface SetupFormValues {
  cf_account_id?: number;
  server_account_id?: number | string;
  purpose?: DomainPurpose;
}

/**
 * Setup on a domain's detail page is a two-stage flow: Save records the
 * Cloudflare account, server account, and purpose on the domain and touches
 * nothing external; the Provision buttons below then act on those saved
 * records (Cloudflare zone setup, cPanel addon domain) only when pressed -
 * so an admin or developer can review the saved records before anything is
 * synced out.
 */
export function SetupPanel({ domain, onUpdated }: { domain: Domain; onUpdated: (domain: Domain) => void }) {
  const { message } = App.useApp();
  const [form] = Form.useForm<SetupFormValues>();
  const [cloudflareAccounts, setCloudflareAccounts] = useState<CloudflareAccount[]>([]);
  const [serverAccounts, setServerAccounts] = useState<ServerAccount[]>([]);
  const [serverGroups, setServerGroups] = useState<ServerGroup[]>([]);
  const [isSaving, setIsSaving] = useState(false);
  const [isProvisioningServer, setIsProvisioningServer] = useState(false);
  const [isProvisioningCloudflare, setIsProvisioningCloudflare] = useState(false);
  const [provisionSteps, setProvisionSteps] = useState<CloudflareProvisionStep[] | null>(null);
  const [blockAiBots, setBlockAiBots] = useState(true);
  const [applyWafPreset, setApplyWafPreset] = useState(true);

  useEffect(() => {
    void Promise.all([listCloudflareAccounts(), listServerAccounts(), listServerGroups()]).then(([cf, servers, groups]) => {
      setCloudflareAccounts(cf);
      setServerAccounts(servers);
      setServerGroups(groups);
    });
  }, []);

  async function applySecurityPresets(domainId: number) {
    const rules = [...(blockAiBots ? [AI_BOT_RULE] : []), ...(applyWafPreset ? WAF_PRESET_RULES : [])];
    for (const rule of rules) {
      try {
        await createSecurityRule(domainId, rule);
      } catch {
        // Best-effort - provisioning itself already succeeded; a preset
        // rule failing shouldn't be treated as a provisioning failure.
      }
    }
  }

  async function handleSave(values: SetupFormValues) {
    setIsSaving(true);
    try {
      const serverAccountId = await resolveServerAccountId(values.server_account_id, domain.fqdn, values.purpose);
      const updated = await updateDomain(domain.id, {
        cf_account_id: values.cf_account_id ?? null,
        server_account_id: serverAccountId ?? null,
        purpose: values.purpose ?? null,
      });
      onUpdated({ ...domain, ...updated });
      message.success("Setup saved. Nothing has been synced yet - use the Provision buttons when ready.");
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't save the setup.");
    } finally {
      setIsSaving(false);
    }
  }

  async function handleProvisionCloudflare() {
    setIsProvisioningCloudflare(true);
    try {
      const result = await provisionCloudflare(domain.id);
      setProvisionSteps(result.steps);
      onUpdated({ ...domain, ...result.domain });
      if (result.steps.every((s) => s.status === "done")) {
        message.success("Cloudflare provisioned.");
        await applySecurityPresets(result.domain.id);
      } else {
        message.warning("Cloudflare provisioning finished with a failed step - see the table below.");
      }
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Cloudflare provisioning failed.");
    } finally {
      setIsProvisioningCloudflare(false);
    }
  }

  async function handleProvisionServer() {
    if (!domain.server_account_id || !domain.purpose) return;

    setIsProvisioningServer(true);
    try {
      const result = await provisionServer(domain.id, {
        server_account_id: domain.server_account_id,
        purpose: domain.purpose,
      });
      onUpdated({ ...domain, ...result.domain });
      message.success("Domain provisioned on the server - cPanel addon domain created.");
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't provision this domain on the server.");
    } finally {
      setIsProvisioningServer(false);
    }
  }

  const canProvisionCloudflare = !!domain.cf_account_id && !!domain.server_account_id;
  const canProvisionServer = !!domain.server_account_id && !!domain.purpose;

  return (
    <Card title="Setup" className="setup-panel dms_domain_setup_panel_card">
      <div className="flex flex-col gap-4">
        <Form<SetupFormValues>
          form={form}
          layout="vertical"
          onFinish={handleSave}
          initialValues={{
            cf_account_id: domain.cf_account_id ?? undefined,
            server_account_id: domain.server_account_id ?? undefined,
            purpose: domain.purpose ?? undefined,
          }}
          className="dms_domain_setup_panel_form"
        >
          <Form.Item name="cf_account_id" label="Cloudflare account" className="dms_domain_setup_panel_cloudflare_account_field">
            <Select
              allowClear
              showSearch
              optionFilterProp="label"
              placeholder="Link a Cloudflare account"
              options={cloudflareAccounts.map((a) => ({ value: a.id, label: a.label }))}
            />
          </Form.Item>

          <Form.Item name="server_account_id" label="Server account" className="dms_domain_setup_panel_server_account_field">
            <Select
              allowClear
              showSearch
              optionFilterProp="label"
              placeholder="Pick the server this domain is held at"
              options={buildServerOptions(serverAccounts, serverGroups)}
            />
          </Form.Item>

          <Form.Item name="purpose" label="Purpose" className="dms_domain_setup_panel_purpose_field">
            <Select allowClear options={PURPOSE_OPTIONS} placeholder="What is this domain for?" />
          </Form.Item>

          <Button type="primary" htmlType="submit" loading={isSaving} className="dms_domain_setup_panel_save_btn">
            Save
          </Button>
        </Form>

        <div className="border-t border-gray-500/20 pt-4 flex flex-col gap-3">
          <div className="text-sm font-medium">Provisioning - acts on the saved records above</div>

          <div>
            <div className="mb-1 text-xs text-gray-500">Security presets, applied once Cloudflare provisioning succeeds</div>
            <Checkbox
              checked={blockAiBots}
              onChange={(e) => setBlockAiBots(e.target.checked)}
              className="dms_domain_setup_panel_block_ai_bots_checkbox"
            >
              Block AI Bots
            </Checkbox>
            <Checkbox
              checked={applyWafPreset}
              onChange={(e) => setApplyWafPreset(e.target.checked)}
              className="dms_domain_setup_panel_waf_preset_checkbox"
            >
              WAF Preset (baseline)
            </Checkbox>
          </div>

          <div className="flex items-center gap-3 flex-wrap">
            <Button
              onClick={handleProvisionCloudflare}
              loading={isProvisioningCloudflare}
              disabled={!canProvisionCloudflare}
              className="dms_domain_setup_panel_provision_cloudflare_btn"
            >
              {domain.cf_zone_id ? "Re-provision Cloudflare" : "Provision Cloudflare"}
            </Button>
            {domain.cf_zone_id && <Tag color="green">Zone linked</Tag>}
            <Button
              onClick={handleProvisionServer}
              loading={isProvisioningServer}
              disabled={!canProvisionServer}
              className="dms_domain_setup_panel_provision_btn"
            >
              Provision on server
            </Button>
          </div>
          {!canProvisionCloudflare && (
            <p className="text-xs text-gray-500">Save a Cloudflare account and a server account to enable Cloudflare provisioning.</p>
          )}
          {!canProvisionServer && (
            <p className="text-xs text-gray-500">Save a server account and a purpose to enable server provisioning.</p>
          )}
        </div>

        {provisionSteps && (
          <Table<CloudflareProvisionStep>
            size="small"
            rowKey="step"
            pagination={false}
            dataSource={provisionSteps}
            columns={[
              { title: "Step", dataIndex: "step" },
              {
                title: "Result",
                dataIndex: "status",
                render: (v: "done" | "failed") => <Tag color={v === "done" ? "green" : "red"}>{v === "done" ? "Done" : "Failed"}</Tag>,
              },
              { title: "Message", dataIndex: "message" },
            ]}
            className="dms_domain_setup_panel_provision_steps_table"
          />
        )}

        {domain.purpose === "html" && (
          <p className="text-xs text-gray-500">Purpose is HTML - upload a zip package from the Deploy tab.</p>
        )}
        {domain.purpose === "wordpress" && (
          <p className="text-xs text-gray-500">Purpose is WordPress - create the site from the Deploy tab.</p>
        )}
        {domain.purpose === "redirect" && (
          <p className="text-xs text-gray-500">Purpose is 301 redirect - set the target in the Redirect tab.</p>
        )}
      </div>
    </Card>
  );
}
