"use client";

import type { Brand, Domain, Region, WpSite } from "@domainops/shared-types";
import { App, Button, Form, Input, Modal, Select, Table, Tag, Tooltip, Typography } from "antd";
import { CopyOutlined, EditOutlined, ExportOutlined, SearchOutlined, TeamOutlined } from "@ant-design/icons";
import type { ColumnsType } from "antd/es/table";
import Link from "next/link";
import { useCallback, useEffect, useState } from "react";
import { listBrands, listRegions } from "@/lib/api/domains";
import { checkWordPress, listWpSites, updateWpSite } from "@/lib/api/wordpress";
import { ApiError } from "@/lib/api/client";
import { useAuth } from "@/lib/auth/AuthProvider";
import { HeldAtTags } from "@/components/features/HeldAtTags";
import { formatDate } from "@/lib/utils/date";
import { serverPaginationConfig, useServerPagination } from "@/lib/hooks/useServerPagination";
import { PageGuide } from "@/components/features/PageGuide";
import { WORDPRESS_GUIDES } from "@/lib/guides/wordpress";
import { PasswordCell } from "./PasswordCell";
import { UsersDrawer } from "./UsersDrawer";

function loginAddress(domain: Domain, site: WpSite): string {
  const path = site.login_url ?? "/wp-admin";

  return `https://${domain.fqdn}${path.startsWith("/") ? path : `/${path}`}`;
}

/**
 * Every domain that runs WordPress, in one place: those the app installed or
 * found (open the login in a new tab, manage the logins - main admin plus
 * extra users with their own role - change or reset passwords, keep notes),
 * and those typed as WordPress that are not registered yet, which get a Check
 * button that looks for an existing install on the server. Passwords stay
 * hidden until someone with the reveal permission asks for one.
 */
export default function WordPressPage() {
  const { message } = App.useApp();
  const { user } = useAuth();
  const [rows, setRows] = useState<Domain[]>([]);
  const [total, setTotal] = useState(0);
  const [isLoading, setIsLoading] = useState(true);
  const { page, pageSize, resetToFirstPage, onChange } = useServerPagination();
  const [search, setSearch] = useState("");
  const [brandId, setBrandId] = useState<number | undefined>();
  const [regionId, setRegionId] = useState<number | undefined>();
  const [sort, setSort] = useState<"domain_asc" | "domain_desc" | "updated_desc">("domain_asc");
  const [brands, setBrands] = useState<Brand[]>([]);
  const [regions, setRegions] = useState<Region[]>([]);
  const [usersDomainId, setUsersDomainId] = useState<number | null>(null);
  const [checkingId, setCheckingId] = useState<number | null>(null);
  const [editing, setEditing] = useState<{ domain: Domain; site: WpSite; field: "login_url" | "notes" } | null>(null);
  const [isSaving, setIsSaving] = useState(false);
  const [editForm] = Form.useForm<{ value: string }>();

  const can = (action: string) => !!user && (user.is_admin || (user.action_permissions ?? []).some((a) => a === "*" || a === action));
  const canManage = can("wp.manage");
  const canReveal = can("wp.reveal");
  const canCheck = can("domain.deploy");

  const load = useCallback(async () => {
    setIsLoading(true);
    try {
      const result = await listWpSites({
        search: search || undefined,
        brand_id: brandId,
        region_id: regionId,
        sort: sort === "updated_desc" ? "updated" : "domain",
        order: sort === "domain_asc" ? "ascend" : "descend",
        page,
        per_page: pageSize,
      });
      setRows(result.data);
      setTotal(result.meta.total);
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't load the WordPress sites.");
    } finally {
      setIsLoading(false);
    }
  }, [search, brandId, regionId, sort, page, pageSize, message]);

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

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

  const usersDomain = rows.find((d) => d.id === usersDomainId) ?? null;

  async function handleCheck(domain: Domain) {
    setCheckingId(domain.id);
    try {
      const result = await checkWordPress(domain.id);
      if (result.status === "not_found") message.warning(result.message);
      else message.success(result.message);
      void load();
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't check this domain.");
    } finally {
      setCheckingId(null);
    }
  }

  async function handleSaveEdit(values: { value: string }) {
    if (!editing) return;
    setIsSaving(true);
    try {
      await updateWpSite(editing.site.id, { [editing.field]: values.value });
      message.success(editing.field === "login_url" ? "Login URL saved." : "Notes saved.");
      setEditing(null);
      void load();
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't save that.");
    } finally {
      setIsSaving(false);
    }
  }

  async function copy(text: string, label: string) {
    try {
      await navigator.clipboard.writeText(text);
      message.success(`${label} copied.`);
    } catch {
      message.error("Couldn't copy.");
    }
  }

  const columns: ColumnsType<Domain> = [
    {
      title: "Domain",
      className: "dms_wp_col_domain",
      render: (_, domain) => (
        <div className="dms_wp_domain_cell">
          <Link href={`/domains/${domain.id}`} className="font-semibold dms_wp_domain_link">
            {domain.fqdn}
          </Link>
          <div className="text-xs opacity-70 dms_wp_domain_meta">
            {[domain.brand?.name, domain.region?.country_code].filter(Boolean).join(" • ") || "—"}
          </div>
        </div>
      ),
    },
    {
      title: "Held At",
      className: "dms_wp_col_held_at",
      render: (_, domain) => (
        <span className="dms_wp_held_at">
          <HeldAtTags account={domain.server_account} />
        </span>
      ),
    },
    {
      title: "WP Admin",
      className: "dms_wp_col_admin",
      render: (_, domain) => {
        const site = domain.wp_site;

        if (!site) {
          return (
            <div className="flex items-center gap-2">
              <Tag className="dms_wp_not_set_up_tag">Not set up</Tag>
              {canCheck && (
                <Tooltip title="Look for an existing WordPress in this domain's folder on the server">
                  <Button
                    size="small"
                    icon={<SearchOutlined />}
                    loading={checkingId === domain.id}
                    disabled={!domain.server_account_id}
                    onClick={() => void handleCheck(domain)}
                    className="dms_wp_check_btn"
                  >
                    Check
                  </Button>
                </Tooltip>
              )}
            </div>
          );
        }

        return (
          <div className="flex items-center gap-1">
            <Tooltip title={loginAddress(domain, site)}>
              <Button size="small" icon={<ExportOutlined />} href={loginAddress(domain, site)} target="_blank" rel="noopener noreferrer" className="dms_wp_open_login_btn">
                WP Admin
              </Button>
            </Tooltip>
            {canManage && (
              <Tooltip title={`Login URL: ${site.login_url}`}>
                <Button
                  size="small"
                  type="text"
                  icon={<EditOutlined />}
                  onClick={() => {
                    setEditing({ domain, site, field: "login_url" });
                    editForm.setFieldsValue({ value: site.login_url });
                  }}
                  className="dms_wp_edit_login_btn"
                />
              </Tooltip>
            )}
          </div>
        );
      },
    },
    {
      title: "Main user",
      className: "dms_wp_col_main_user",
      render: (_, domain) => {
        const users = domain.wp_site?.users ?? [];
        const main = users.find((u) => u.is_primary) ?? users[0];

        return main ? (
          <span className="flex items-center gap-1 dms_wp_main_user">
            <span className="dms_wp_main_user_name">{main.username}</span>
            <Button size="small" type="text" icon={<CopyOutlined />} onClick={() => void copy(main.username, "Username")} className="dms_wp_copy_user_btn" />
          </span>
        ) : (
          "—"
        );
      },
    },
    {
      title: "Main pass",
      className: "dms_wp_col_main_pass",
      render: (_, domain) => {
        const users = domain.wp_site?.users ?? [];
        const main = users.find((u) => u.is_primary) ?? users[0];

        return main ? <PasswordCell user={main} canReveal={canReveal} canManage={canManage} onChanged={() => void load()} /> : "—";
      },
    },
    {
      title: "Users",
      className: "dms_wp_col_users",
      render: (_, domain) =>
        domain.wp_site ? (
          <Button size="small" icon={<TeamOutlined />} onClick={() => setUsersDomainId(domain.id)} className="dms_wp_users_btn">
            {domain.wp_site.users?.length ?? 0} {(domain.wp_site.users?.length ?? 0) === 1 ? "user" : "users"}
          </Button>
        ) : (
          "—"
        ),
    },
    {
      title: "Notes",
      className: "dms_wp_col_notes",
      render: (_, domain) => {
        const site = domain.wp_site;
        if (!site) return "—";

        return (
          <div className="flex items-start gap-1 dms_wp_notes" style={{ maxWidth: 260 }}>
            <span className="text-sm dms_wp_notes_text" style={{ whiteSpace: "pre-wrap" }}>
              {site.notes || "—"}
            </span>
            {canManage && (
              <Button
                size="small"
                type="text"
                icon={<EditOutlined />}
                onClick={() => {
                  setEditing({ domain, site, field: "notes" });
                  editForm.setFieldsValue({ value: site.notes ?? "" });
                }}
                className="dms_wp_edit_notes_btn"
              />
            )}
          </div>
        );
      },
    },
    {
      title: "Installed",
      className: "dms_wp_col_installed",
      render: (_, domain) => {
        const site = domain.wp_site;
        if (!site) return "—";

        return (
          <div className="text-xs dms_wp_installed">
            <span className="dms_wp_installed_date">{formatDate(site.created_at)}</span>
            <div>
              <Tag className="dms_wp_installed_version_tag">{site.core_version ? `WP ${site.core_version}` : site.install_method === "wp_toolkit" ? "WP Toolkit" : "WP-CLI"}</Tag>
            </div>
          </div>
        );
      },
    },
  ];

  return (
    <div className="flex flex-col gap-4 page page-wordpress dms_wp_page">
      <div className="dms_wp_header">
        <div className="flex items-center gap-2 dms_wp_title_row">
          <Typography.Title level={4} style={{ margin: 0 }} className="dms_wp_title">
            WordPress
          </Typography.Title>
          <PageGuide guides={WORDPRESS_GUIDES} label="WordPress guide" />
        </div>
        <Typography.Text type="secondary" className="dms_wp_count">
          {total} {total === 1 ? "site" : "sites"}
        </Typography.Text>
      </div>

      <div className="dms_domains_filters dms_wp_filters">
        <Input.Search
          allowClear
          placeholder="Search domain or project..."
          className="dms_wp_search_input"
          onSearch={(value) => {
            resetToFirstPage();
            setSearch(value);
          }}
        />
        <Select
          allowClear
          showSearch
          optionFilterProp="label"
          placeholder="All projects"
          className="dms_wp_project_filter"
          options={brands.map((b) => ({ value: b.id, label: b.name }))}
          onChange={(value) => {
            resetToFirstPage();
            setBrandId(value);
          }}
        />
        <Select
          allowClear
          showSearch
          optionFilterProp="label"
          placeholder="All countries"
          className="dms_wp_country_filter"
          options={regions.map((r) => ({ value: r.id, label: `${r.name} (${r.country_code})` }))}
          onChange={(value) => {
            resetToFirstPage();
            setRegionId(value);
          }}
        />
        <Select
          value={sort}
          className="dms_wp_sort_select"
          onChange={(value) => {
            resetToFirstPage();
            setSort(value);
          }}
          options={[
            { value: "domain_asc", label: "Sort: Domain A-Z" },
            { value: "domain_desc", label: "Sort: Domain Z-A" },
            { value: "updated_desc", label: "Sort: Recently updated" },
          ]}
        />
      </div>

      <Table<Domain>
        rowKey="id"
        columns={columns}
        dataSource={rows}
        loading={isLoading}
        scroll={{ x: "max-content" }}
        pagination={serverPaginationConfig(total, page, pageSize, onChange, "sites")}
        className="dms_wp_table"
      />

      <UsersDrawer
        domain={usersDomain}
        open={usersDomain !== null}
        canReveal={canReveal}
        canManage={canManage}
        onClose={() => setUsersDomainId(null)}
        onChanged={() => void load()}
      />

      <Modal
        title={editing?.field === "login_url" ? `Login URL - ${editing.domain.fqdn}` : `Notes - ${editing?.domain.fqdn ?? ""}`}
        open={!!editing}
        onCancel={() => setEditing(null)}
        onOk={() => editForm.submit()}
        confirmLoading={isSaving}
        okText="Save"
        mask={{ closable: false }}
        destroyOnHidden
        className="dms_wp_edit_modal"
      >
        <Form form={editForm} layout="vertical" onFinish={handleSaveEdit} className="dms_wp_edit_form">
          <Form.Item
            className="dms_wp_edit_value_field"
            name="value"
            label={editing?.field === "login_url" ? "Path after the domain" : "Notes"}
            extra={editing?.field === "login_url" ? "/wp-admin by default; /wp-login.php or a custom path if the site hides its login." : undefined}
            rules={editing?.field === "login_url" ? [{ required: true, message: "Enter the login path" }] : []}
          >
            {editing?.field === "login_url" ? <Input placeholder="/wp-admin" className="dms_wp_edit_login_input" /> : <Input.TextArea rows={4} className="dms_wp_edit_notes_input" />}
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
}
