import { useStore } from '@nanostores/react';
import { useFetcher } from '@remix-run/react';
import classNames from 'classnames';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { toast } from 'sonner';
import { NetlifyDeploymentLink } from '~/components/chat/NetlifyDeploymentLink.client';
import useViewport from '~/lib/hooks';
import { setLocalStorage } from '~/lib/persistence';
import { aiState, setShowChat } from '~/lib/stores/ai-state';
import { webBuilderStore } from '~/lib/stores/web-builder';
import type { _1PanelDeployResponse } from '~/types/1panel';
import { DeploymentPlatformEnum } from '~/types/deployment';
import type { ApiResponse } from '~/types/global';
import { _1PanelDeploymentLink } from '../chat/_1PanelDeploymentLink.client';
import { VercelDeploymentLink } from '../chat/VercelDeploymentLink.client';
import { UPageIndex } from '../upage/Index';
import { DeployTo1PanelDialog } from './DeployTo1PanelDialog';
import { DeployToNetlifyDialog } from './DeployToNetlifyDialog';
import { DeployToVercelDialog } from './DeployToVercelDialog';

interface HeaderActionButtonsProps {}

export function HeaderActionButtons({}: HeaderActionButtonsProps) {
  const showWorkbench = useStore(webBuilderStore.showWorkbench);
  const { showChat, chatId, isStreaming } = useStore(aiState);
  const [deployingTo, setDeployingTo] = useState<'netlify' | 'vercel' | '1panel' | null>(null);
  const isSmallViewport = useViewport(1024);

  const canHideChat = showWorkbench || !showChat;
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);
  const dropdownRef = useRef<HTMLDivElement>(null);

  const netlifyFetcher = useFetcher<ApiResponse>();
  const vercelFetcher = useFetcher<ApiResponse>();
  const panelFetcher = useFetcher<_1PanelDeployResponse>();

  const isDeploying = useMemo(() => {
    return netlifyFetcher.state !== 'idle' || vercelFetcher.state !== 'idle' || panelFetcher.state !== 'idle';
  }, [netlifyFetcher.state, vercelFetcher.state, panelFetcher.state]);

  const [showNetlifyDialog, setShowNetlifyDialog] = useState(false);
  const [showVercelDialog, setShowVercelDialog] = useState(false);
  const [show1PanelDialog, setShow1PanelDialog] = useState(false);

  useEffect(() => {
    const url = new URL(window.location.href);
    const deploy = url.searchParams.get('deploy');
    switch (deploy) {
      case DeploymentPlatformEnum.NETLIFY:
        setShowNetlifyDialog(true);
        break;
      case DeploymentPlatformEnum.VERCEL:
        setShowVercelDialog(true);
        break;
      case DeploymentPlatformEnum._1PANEL:
        setShow1PanelDialog(true);
        break;
    }
    const recommend = url.searchParams.get('recommend');
    if (recommend) {
      setLocalStorage('recommend', recommend || '');
    }
    if (deploy || recommend) {
      url.searchParams.delete('deploy');
      url.searchParams.delete('recommend');
      window.history.replaceState({}, '', url);
    }
  }, []);

  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
        setIsDropdownOpen(false);
      }
    }
    document.addEventListener('mousedown', handleClickOutside);

    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  useEffect(() => {
    if (netlifyFetcher.state === 'idle' && netlifyFetcher.data) {
      const { data, success, message } = netlifyFetcher.data;

      if (success && data?.deploy && data?.site) {
        if (data.site) {
          localStorage.setItem(`netlify-site-${chatId!}`, data.site?.id);
        }

        toast.success(
          <div>
            部署成功!{' '}
            <a href={data.deploy.url} target="_blank" rel="noopener noreferrer" className="underline">
              查看站点
            </a>
          </div>,
        );

        setShowNetlifyDialog(false);
      } else {
        console.error('Invalid deploy response:', data);
        toast.error(message || 'Invalid deployment response');
      }

      setDeployingTo(null);
    }
  }, [netlifyFetcher.state, netlifyFetcher.data, chatId]);

  useEffect(() => {
    if (vercelFetcher.state === 'idle' && vercelFetcher.data) {
      const { data, success, message } = vercelFetcher.data;

      if (success && data?.deploy && data?.project) {
        if (data.project) {
          localStorage.setItem(`vercel-project-${chatId!}`, data.project.id);
        }

        toast.success(
          <div>
            部署到 Vercel 成功!{' '}
            <a href={data.deploy.url} target="_blank" rel="noopener noreferrer" className="underline">
              查看站点
            </a>
          </div>,
        );

        setShowVercelDialog(false);
      } else {
        console.error('Invalid deploy response:', data);
        toast.error(message || 'Invalid deployment response');
      }

      setDeployingTo(null);
    }
  }, [vercelFetcher.state, vercelFetcher.data, chatId]);

  useEffect(() => {
    if (panelFetcher.state === 'idle' && panelFetcher.data) {
      const data = panelFetcher.data as _1PanelDeployResponse;

      const { deploy } = data.data || {};
      if (data.success && deploy) {
        localStorage.setItem(`1panel-project-${chatId!}`, deploy.id.toString());

        toast.success(
          <div>
            部署到 1Panel 成功!{' '}
            <a href={deploy.url} target="_blank" rel="noopener noreferrer" className="underline">
              查看站点
            </a>
          </div>,
        );

        setShow1PanelDialog(false);
      } else {
        console.error('Invalid deploy response:', data);
        toast.error(data.message || 'Invalid deployment response');
      }

      setDeployingTo(null);
    }
  }, [panelFetcher.state, panelFetcher.data, chatId]);

  async function getAllFiles(): Promise<Record<string, string>> {
    const files = await webBuilderStore.getProjectFiles({ inline: false }).then((files) => {
      return files.reduce(
        (acc, file) => {
          acc[file.filename] = file.content;
          return acc;
        },
        {} as Record<string, string>,
      );
    });
    const newFiles: Record<string, string> = {};
    for (const [key, value] of Object.entries(files)) {
      if (key.endsWith('.html')) {
        const html = new DOMParser().parseFromString(value, 'text/html');
        const originalContent = html.body.innerHTML;
        // 添加 UPageHtml 到 body 中
        const uPageHtml = renderToStaticMarkup(<UPageIndex />);
        html.body.innerHTML = originalContent + uPageHtml;
        newFiles[key] = '<!DOCTYPE html>\n' + html.documentElement.outerHTML;
      } else {
        newFiles[key] = value;
      }
    }
    return newFiles;
  }

  const handleNetlifyDeploy = useCallback(async () => {
    if (!chatId) {
      toast.error('没有找到活动聊天');
      return;
    }

    try {
      setDeployingTo('netlify');

      const fileContents = await getAllFiles();
      const existingSiteId = localStorage.getItem(`netlify-site-${chatId}`);

      netlifyFetcher.submit(
        {
          siteId: existingSiteId || '',
          files: fileContents,
          chatId: chatId!,
        } as any,
        {
          method: 'POST',
          action: '/api/netlify/deploy',
          encType: 'application/json',
        },
      );
    } catch (error) {
      console.error('Deploy error:', error);
      toast.error(error instanceof Error ? error.message : '部署失败');
      setDeployingTo(null);
    }
  }, [chatId, netlifyFetcher]);

  const handleVercelDeploy = useCallback(async () => {
    if (!chatId) {
      toast.error('没有找到活动聊天');
      return;
    }

    try {
      setDeployingTo('vercel');

      const fileContents = await getAllFiles();
      const existingProjectId = localStorage.getItem(`vercel-project-${chatId}`);

      vercelFetcher.submit(
        {
          projectId: existingProjectId || '',
          files: fileContents,
          chatId: chatId!,
        } as any,
        {
          method: 'POST',
          action: '/api/vercel/deploy',
          encType: 'application/json',
        },
      );
    } catch (error) {
      console.error('Vercel deploy error:', error);
      toast.error(error instanceof Error ? error.message : 'Vercel 部署失败');
      setDeployingTo(null);
    }
  }, [chatId, vercelFetcher]);

  const handle1PanelDeploy = useCallback(
    async (options?: { customDomain?: string; siteId?: number; protocol?: string }) => {
      if (!chatId) {
        toast.error('没有找到活动聊天');
        return;
      }

      try {
        setDeployingTo('1panel');

        const fileContents = await getAllFiles();
        const existingWebsiteId = localStorage.getItem(`1panel-project-${chatId}`);

        panelFetcher.submit(
          {
            websiteId: options?.siteId || existingWebsiteId || '',
            websiteDomain: options?.customDomain || '',
            protocol: options?.protocol || 'http',
            files: fileContents,
            chatId: chatId!,
          } as any,
          {
            method: 'POST',
            action: '/api/1panel/deploy',
            encType: 'application/json',
          },
        );
      } catch (error) {
        console.error('1Panel deploy error:', error);
        toast.error(error instanceof Error ? error.message : '1Panel 部署失败');
        setDeployingTo(null);
      }
    },
    [chatId, panelFetcher],
  );

  return (
    <div className="flex">
      <div className="relative" ref={dropdownRef}>
        <div className="flex border border-upage-elements-borderColor rounded-md overflow-hidden mr-2 text-sm">
          <Button
            active
            disabled={isDeploying || isStreaming}
            onClick={() => {
              if (isDeploying || isStreaming) {
                return;
              }
              setShow1PanelDialog(true);
            }}
            className="px-4 hover:bg-upage-elements-item-backgroundActive flex items-center gap-2"
          >
            <div className="i-mingcute:rocket-line size-4" />
            {isDeploying ? `部署至 ${deployingTo} 中...` : '部署'}
          </Button>
          <div className="w-[1px] bg-upage-elements-borderColor" />
          <Button
            active
            disabled={isDeploying || isStreaming}
            onClick={() => {
              if (isDeploying || isStreaming) {
                return;
              }
              setIsDropdownOpen(!isDropdownOpen);
            }}
          >
            <div
              className={classNames('i-ph:caret-down size-4 transition-transform', isDropdownOpen ? 'rotate-180' : '')}
            />
          </Button>
        </div>

        {isDropdownOpen && (
          <div className="absolute right-2 flex flex-col gap-1 z-50 p-1 mt-1 min-w-[14rem] bg-upage-elements-background-depth-2 rounded-md shadow-lg bg-upage-elements-backgroundDefault border border-upage-elements-borderColor">
            <Button
              onClick={() => {
                setShow1PanelDialog(true);
                setIsDropdownOpen(false);
              }}
              disabled={isDeploying}
              className="flex items-center w-full px-4 py-2 text-sm text-upage-elements-textPrimary gap-3 rounded-md group relative"
            >
              <img src="/icons/1panel.png" alt="1Panel" className="size-5" />
              <span>部署到 1Panel</span>
              <_1PanelDeploymentLink />
            </Button>
            <Button
              onClick={() => {
                setShowNetlifyDialog(true);
                setIsDropdownOpen(false);
              }}
              disabled={isDeploying}
              className="flex items-center w-full px-4 py-2 text-sm text-upage-elements-textPrimary gap-3 rounded-md group relative"
            >
              <div className="i-simple-icons:netlify size-5 bg-#00C7B7"></div>
              <span>部署到 Netlify</span>
              <NetlifyDeploymentLink />
            </Button>
            <Button
              onClick={() => {
                setShowVercelDialog(true);
                setIsDropdownOpen(false);
              }}
              disabled={isDeploying}
              className="flex items-center w-full px-4 py-2 text-sm text-upage-elements-textPrimary gap-3 rounded-md group relative"
            >
              <div className="i-skill-icons:vercel-light size-5"></div>
              <span>部署到 Vercel</span>
              <VercelDeploymentLink />
            </Button>
          </div>
        )}
      </div>
      <div className="flex border border-upage-elements-borderColor rounded-md overflow-hidden mr-2">
        <Button
          active={showChat}
          disabled={!canHideChat || isSmallViewport}
          onClick={() => {
            if (canHideChat) {
              setShowChat(!showChat);
            }
          }}
        >
          <div className="i-mingcute:chat-2-line text-sm" />
        </Button>
        <div className="w-[1px] bg-upage-elements-borderColor" />
        <Button
          active={showWorkbench}
          onClick={() => {
            if (showWorkbench && !showChat) {
              setShowChat(true);
            }

            webBuilderStore.showWorkbench.set(!showWorkbench);
          }}
        >
          <div className="i-mingcute:code-line" />
        </Button>
      </div>
      <DeployToNetlifyDialog
        isOpen={showNetlifyDialog}
        deploying={isDeploying}
        onClose={() => setShowNetlifyDialog(false)}
        onDeploy={handleNetlifyDeploy}
      />
      <DeployToVercelDialog
        isOpen={showVercelDialog}
        deploying={isDeploying}
        onClose={() => setShowVercelDialog(false)}
        onDeploy={handleVercelDeploy}
      />
      <DeployTo1PanelDialog
        isOpen={show1PanelDialog}
        deploying={isDeploying}
        onClose={() => setShow1PanelDialog(false)}
        onDeploy={handle1PanelDeploy}
      />
    </div>
  );
}

interface ButtonProps {
  active?: boolean;
  disabled?: boolean;
  children?: any;
  onClick?: VoidFunction;
  className?: string;
}

function Button({ active = false, disabled = false, children, onClick, className }: ButtonProps) {
  return (
    <button
      className={classNames(
        'flex items-center p-1.5',
        {
          'bg-upage-elements-item-backgroundDefault hover:bg-upage-elements-item-backgroundAccent text-upage-elements-textPrimary hover:text-upage-elements-item-contentAccent':
            !active,
          'bg-upage-elements-item-backgroundAccent text-upage-elements-item-contentAccent': active && !disabled,
          'bg-upage-elements-item-backgroundAccent text-upage-elements-item-contentAccent cursor-not-allowed':
            active && disabled,
          'bg-upage-elements-item-backgroundDefault text-alpha-gray-20 dark:text-alpha-white-20 cursor-not-allowed':
            !active && disabled,
        },
        className,
      )}
      onClick={onClick}
    >
      {children}
    </button>
  );
}
