"use client";

import type { Domain, SeoAccessCheck } from "@domainops/shared-types";
import { App, Button, Card, Descriptions, Divider, Radio, Switch, Tag, Upload } from "antd";
import { UploadOutlined } from "@ant-design/icons";
import { useState } from "react";
import { checkSeoAccess, generateRobotsFile, toggleRobots, uploadSitemap } from "@/lib/api/seo";
import { updateDomain } from "@/lib/api/domains";
import { ApiError } from "@/lib/api/client";
import { confirmRobotsChange } from "@/lib/utils/robotsConfirm";
import { GscTxtSection } from "@/components/features/GscTxtSection";

export function SeoPanel({
  domain,
  hasServer,
  onUpdated,
}: {
  domain: Domain;
  hasServer: boolean;
  onUpdated: (domain: Domain) => void;
}) {
  const { message, modal } = App.useApp();
  const [isToggling, setIsToggling] = useState(false);
  const [isChecking, setIsChecking] = useState(false);
  const [access, setAccess] = useState<SeoAccessCheck | null>(null);
  const [isGeneratingRobots, setIsGeneratingRobots] = useState(false);
  const [isUploadingSitemap, setIsUploadingSitemap] = useState(false);
  const [isSavingSitemapName, setIsSavingSitemapName] = useState(false);

  async function handleToggle(checked: boolean) {
    setIsToggling(true);
    try {
      const updated = await toggleRobots(domain.id, checked);
      onUpdated(updated);
      message.success(checked ? "Now indexable." : "Now noindex.");
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't change that.");
    } finally {
      setIsToggling(false);
    }
  }

  async function handleCheck() {
    setIsChecking(true);
    try {
      setAccess(await checkSeoAccess(domain.id));
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't check access.");
    } finally {
      setIsChecking(false);
    }
  }

  async function handleGenerateRobots(overwrite: boolean) {
    setIsGeneratingRobots(true);
    try {
      const updated = await generateRobotsFile(domain.id, overwrite);
      onUpdated(updated);
      if (updated.robots_created) message.success("robots.txt created on the server.");
      else message.info("robots.txt already exists on the server - left as it is.");
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't create robots.txt.");
    } finally {
      setIsGeneratingRobots(false);
    }
  }

  async function handleSitemapName(value: "sitemap.xml" | "sitemap_index.xml") {
    setIsSavingSitemapName(true);
    try {
      onUpdated(await updateDomain(domain.id, { sitemap_filename: value }));
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't save the sitemap file name.");
    } finally {
      setIsSavingSitemapName(false);
    }
  }

  async function handleUploadSitemap(file: File) {
    setIsUploadingSitemap(true);
    try {
      onUpdated(await uploadSitemap(domain.id, file));
      message.success(`${domain.sitemap_filename} uploaded to the server.`);
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't upload that sitemap.");
    } finally {
      setIsUploadingSitemap(false);
    }
  }

  return (
    <Card title="SEO" className="dms_domain_seo_panel_card">
      <div className="mb-4">
        <div className="flex items-center gap-3">
          <Switch
            checked={domain.robots_state === "index"}
            onChange={(checked) => confirmRobotsChange(modal, domain.fqdn, checked, () => handleToggle(checked))}
            disabled={!hasServer}
            loading={isToggling}
            className="dms_domain_seo_panel_visibility_switch"
          />
          <span>{domain.robots_state === "index" ? "Index, Follow" : "Noindex, Nofollow"}</span>
        </div>
        <div className="text-xs text-gray-500 mt-1">
          Website Visibility - whether search engines are allowed to list and crawl links on this site.
        </div>
      </div>

      <div className="mb-3 dms_domain_seo_panel_sitemap_name">
        <div className="text-sm mb-1">Sitemap file</div>
        <Radio.Group
          value={domain.sitemap_filename}
          onChange={(event) => void handleSitemapName(event.target.value)}
          disabled={isSavingSitemapName}
          optionType="button"
          options={[
            { value: "sitemap.xml", label: "sitemap.xml" },
            { value: "sitemap_index.xml", label: "sitemap_index.xml" },
          ]}
          className="dms_domain_seo_panel_sitemap_name_radio"
        />
        <div className="text-xs text-gray-500 mt-1">
          Pick the name this site uses - WordPress SEO plugins often publish <b>sitemap_index.xml</b>. It is used for the robots.txt Sitemap line, the access check and the upload below.
        </div>
      </div>

      <div className="flex flex-wrap gap-2 mb-3">
        <Button onClick={handleCheck} loading={isChecking} size="small" className="dms_domain_seo_panel_check_access_btn">
          Ping sitemap &amp; check robots.txt
        </Button>
        <Button
          onClick={() => void handleGenerateRobots(false)}
          loading={isGeneratingRobots}
          size="small"
          disabled={!hasServer}
          className="dms_domain_seo_panel_generate_robots_btn"
        >
          Generate robots.txt
        </Button>
        <Upload
          accept=".xml,text/xml,application/xml"
          showUploadList={false}
          disabled={!hasServer || isUploadingSitemap}
          beforeUpload={(file) => {
            void handleUploadSitemap(file);

            return false;
          }}
        >
          <Button size="small" icon={<UploadOutlined />} loading={isUploadingSitemap} disabled={!hasServer} className="dms_domain_seo_panel_upload_sitemap_btn">
            Upload {domain.sitemap_filename}
          </Button>
        </Upload>
      </div>
      <div className="text-xs text-gray-500 mb-3 dms_domain_seo_panel_robots_hint">
        Generate robots.txt only writes the file when the server folder does not have one yet ({domain.robots_state === "index" ? `User-agent: *, empty Disallow, Sitemap: https://${domain.fqdn}/${domain.sitemap_filename}` : "User-agent: *, Disallow: / while the site is noindex"}).
      </div>

      {access && (
        <Descriptions size="small" column={1} className="mt-3">
          <Descriptions.Item label="robots.txt">
            <Tag color={access.robots_txt === "reachable" ? "green" : "default"}>{access.robots_txt}</Tag>
          </Descriptions.Item>
          <Descriptions.Item label="sitemap.xml">
            <Tag color={access.sitemap_xml === "reachable" ? "green" : "default"}>{access.sitemap_xml}</Tag>
          </Descriptions.Item>
          <Descriptions.Item label="robots.txt points to sitemap">
            <Tag
              color={
                access.robots_points_to_sitemap === "yes"
                  ? "green"
                  : access.robots_points_to_sitemap === "no"
                    ? "red"
                    : "default"
              }
            >
              {access.robots_points_to_sitemap}
            </Tag>
          </Descriptions.Item>
        </Descriptions>
      )}

      <Divider style={{ margin: "16px 0" }} />

      <GscTxtSection domain={domain} onUpdated={onUpdated} />
    </Card>
  );
}
