import {
  ArrowLeftOutlined,
  CheckSquareOutlined,
  CompressOutlined,
  CopyOutlined,
  DeleteOutlined,
  EyeOutlined,
  ExpandOutlined,
  FileTextOutlined,
  PlayCircleOutlined,
  PlusOutlined,
  SaveOutlined,
} from '@ant-design/icons';
import { Button, Card, Checkbox, Empty, Flex, Input, List, Segmented, Select, Space, Spin, Tag, Typography, message } from 'antd';
import { useEffect, useMemo, useState } from 'react';
import { MarkdownPreviewContent } from '../../components/markdownPreview';
import {
  createBoardPost,
  deleteBoardPost,
  fetchBoardPosts,
  receiveBoardPostAutomation,
  setupBoard,
  updateBoardPost,
} from './api';
import type { BoardAutomationType, BoardDraft, BoardPost } from './types';

const { Paragraph, Text, Title } = Typography;
const { TextArea } = Input;

const EMPTY_DRAFT: BoardDraft = {
  id: null,
  title: '',
  content: '',
  automationType: 'none',
};

const BOARD_AUTOMATION_TYPE_OPTIONS: Array<{ label: string; value: BoardAutomationType }> = [
  { label: '선택 안함', value: 'none' },
  { label: 'Plan', value: 'plan' },
  { label: 'Command 실행', value: 'command_execution' },
  { label: '비 소스작업', value: 'non_source_work' },
  { label: 'autoWorker', value: 'auto_worker' },
];

const BOARD_AUTOMATION_TYPE_LABELS = new Map(
  BOARD_AUTOMATION_TYPE_OPTIONS.map((option) => [option.value, option.label] as const),
);

function formatDateTime(value: string) {
  return new Date(value).toLocaleString('ko-KR', {
    timeZone: 'Asia/Seoul',
  });
}

async function copyText(value: string) {
  if (navigator.clipboard?.writeText) {
    await navigator.clipboard.writeText(value);
    return;
  }

  const textArea = document.createElement('textarea');
  textArea.value = value;
  textArea.setAttribute('readonly', '');
  textArea.style.position = 'fixed';
  textArea.style.left = '-9999px';
  document.body.appendChild(textArea);
  textArea.select();
  document.execCommand('copy');
  document.body.removeChild(textArea);
}

function resolveBoardAutomationStatus(
  draftId: number | null,
  automationReceived: boolean,
  draftDirty: boolean,
  errorMessage: string | null,
) {
  if (errorMessage) {
    return {
      color: 'error',
      label: '접수 실패',
      description: errorMessage,
    };
  }

  if (!draftId) {
    return {
      color: 'default',
      label: '저장 필요',
      description: '저장 후 자동화 접수 가능',
    };
  }

  if (draftDirty) {
    return {
      color: 'warning',
      label: '저장 필요',
      description: '변경 내용을 저장한 뒤 접수',
    };
  }

  if (automationReceived) {
    return {
      color: 'processing',
      label: '접수완료',
      description: '연결된 Plan에서 작업 상태 확인',
    };
  }

  return {
    color: 'default',
    label: '대기',
    description: '자동화 접수 전',
  };
}

function getBoardPostAutomationReceiveError(item: BoardPost, dirtyDraftId: number | null) {
  if (item.id === dirtyDraftId) {
    return '변경 내용을 저장한 뒤 자동화 접수하세요.';
  }

  if (item.automationReceivedAt || item.automationPlanItemId) {
    return '이미 자동화 접수된 게시글입니다.';
  }

  return null;
}

export function BoardPage() {
  const [messageApi, contextHolder] = message.useMessage();
  const [items, setItems] = useState<BoardPost[]>([]);
  const [selectedId, setSelectedId] = useState<number | null>(null);
  const [checkedIds, setCheckedIds] = useState<number[]>([]);
  const [draft, setDraft] = useState<BoardDraft>(EMPTY_DRAFT);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [deleting, setDeleting] = useState(false);
  const [automationReceiving, setAutomationReceiving] = useState(false);
  const [automationReceiveError, setAutomationReceiveError] = useState<string | null>(null);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [isMobileViewport, setIsMobileViewport] = useState(false);
  const [mobileDetailOpen, setMobileDetailOpen] = useState(false);
  const [mobileView, setMobileView] = useState<'edit' | 'preview'>('edit');
  const [contentExpanded, setContentExpanded] = useState(false);

  useEffect(() => {
    if (typeof window === 'undefined') {
      return;
    }

    const mediaQuery = window.matchMedia('(max-width: 960px)');
    const update = () => {
      setIsMobileViewport(mediaQuery.matches);
      if (!mediaQuery.matches) {
        setMobileDetailOpen(false);
      }
    };

    update();
    mediaQuery.addEventListener('change', update);

    return () => {
      mediaQuery.removeEventListener('change', update);
    };
  }, []);

  useEffect(() => {
    let cancelled = false;

    const load = async () => {
      setLoading(true);
      setErrorMessage(null);

      try {
        await setupBoard();
        const nextItems = await fetchBoardPosts();

        if (cancelled) {
          return;
        }

        setItems(nextItems);
        setSelectedId((previous) => previous ?? nextItems[0]?.id ?? null);
      } catch (error) {
        if (!cancelled) {
          setErrorMessage(error instanceof Error ? error.message : '게시판을 불러오지 못했습니다.');
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    };

    void load();

    return () => {
      cancelled = true;
    };
  }, []);

  const selectedItem = useMemo(
    () => items.find((item) => item.id === selectedId) ?? null,
    [items, selectedId],
  );
  const showMobileDetailOnly = isMobileViewport && mobileDetailOpen;
  const automationReceived = Boolean(selectedItem?.automationReceivedAt || selectedItem?.automationPlanItemId);
  const isDraftLocked = automationReceived;
  const draftDirty = Boolean(
    selectedItem &&
      (
        draft.title !== selectedItem.title ||
        draft.content !== selectedItem.content ||
        draft.automationType !== selectedItem.automationType
      ),
  );
  const dirtyDraftId = draftDirty && draft.id ? draft.id : null;
  const automationStatus = resolveBoardAutomationStatus(draft.id, automationReceived, draftDirty, automationReceiveError);
  const automationTypeLabel = BOARD_AUTOMATION_TYPE_LABELS.get(draft.automationType) ?? draft.automationType;
  const receivableIds = useMemo(
    () =>
      items
        .filter((item) => !getBoardPostAutomationReceiveError(item, dirtyDraftId))
        .map((item) => item.id),
    [dirtyDraftId, items],
  );
  const receivableIdSet = useMemo(() => new Set(receivableIds), [receivableIds]);
  const checkedReceivableCount = checkedIds.filter((id) => receivableIdSet.has(id)).length;
  const allReceivableChecked = receivableIds.length > 0 && checkedReceivableCount === receivableIds.length;
  const partiallyChecked = checkedReceivableCount > 0 && checkedReceivableCount < receivableIds.length;

  useEffect(() => {
    if (selectedItem) {
      setDraft({
        id: selectedItem.id,
        title: selectedItem.title,
        content: selectedItem.content,
        automationType: selectedItem.automationType,
      });
      setAutomationReceiveError(null);
      return;
    }

    setDraft(EMPTY_DRAFT);
    setAutomationReceiveError(null);
  }, [selectedItem]);

  useEffect(() => {
    const itemIdSet = new Set(items.map((item) => item.id));
    setCheckedIds((previous) => previous.filter((id) => itemIdSet.has(id)));
  }, [items]);

  const handleCreateDraft = () => {
    setSelectedId(null);
    setDraft(EMPTY_DRAFT);
    setAutomationReceiveError(null);
    setMobileDetailOpen(isMobileViewport);
  };

  const handleSave = async () => {
    const normalizedTitle = draft.title.trim();
    const normalizedContent = draft.content.trim();

    if (!normalizedTitle) {
      messageApi.warning('제목을 입력하세요.');
      return;
    }

    if (!normalizedContent) {
      messageApi.warning('본문을 입력하세요.');
      return;
    }

    setSaving(true);
    setAutomationReceiveError(null);

    try {
      const savedItem = draft.id
        ? await updateBoardPost({
            ...draft,
            title: normalizedTitle,
            content: normalizedContent,
          })
        : await createBoardPost({
            ...draft,
            title: normalizedTitle,
            content: normalizedContent,
          });

      setItems((previous) => {
        const filtered = previous.filter((item) => item.id !== savedItem.id);
        return [savedItem, ...filtered];
      });
      setSelectedId(savedItem.id);
      setMobileDetailOpen(isMobileViewport);
      messageApi.success(draft.id ? '게시글을 수정했습니다.' : '게시글을 등록했습니다.');
    } catch (error) {
      messageApi.error(error instanceof Error ? error.message : '게시글 저장에 실패했습니다.');
    } finally {
      setSaving(false);
    }
  };

  const handleDelete = async () => {
    if (!draft.id) {
      handleCreateDraft();
      return;
    }

    setDeleting(true);

    try {
      await deleteBoardPost(draft.id);
      setItems((previous) => previous.filter((item) => item.id !== draft.id));
      setSelectedId((previous) => (previous === draft.id ? null : previous));
      setDraft(EMPTY_DRAFT);
      setMobileDetailOpen(false);
      messageApi.success('게시글을 삭제했습니다.');
    } catch (error) {
      messageApi.error(error instanceof Error ? error.message : '게시글 삭제에 실패했습니다.');
    } finally {
      setDeleting(false);
    }
  };

  const handleCopyContent = async () => {
    if (!draft.content.trim()) {
      messageApi.warning('복사할 본문이 없습니다.');
      return;
    }

    try {
      await copyText(draft.content);
      messageApi.success('본문을 복사했습니다.');
    } catch (error) {
      messageApi.error(error instanceof Error ? error.message : '본문 복사에 실패했습니다.');
    }
  };

  const handleAutomationReceive = async () => {
    if (!draft.id) {
      messageApi.warning('저장된 게시글만 자동화 접수할 수 있습니다.');
      return;
    }

    if (draftDirty) {
      messageApi.warning('변경 내용을 저장한 뒤 자동화 접수하세요.');
      return;
    }

    if (automationReceived) {
      messageApi.info('이미 자동화 접수된 게시글입니다.');
      return;
    }

    setAutomationReceiving(true);
    setAutomationReceiveError(null);

    try {
      const result = await receiveBoardPostAutomation(draft.id);
      setItems((previous) => previous.map((item) => (item.id === result.item.id ? result.item : item)));
      messageApi.success(
        result.alreadyReceived
          ? '이미 자동화 접수된 게시글입니다.'
          : `자동화 접수했습니다. Plan #${result.planItemId}`,
      );
    } catch (error) {
      const message = error instanceof Error ? error.message : '자동화 접수에 실패했습니다.';
      setAutomationReceiveError(message);
      messageApi.error(message);
    } finally {
      setAutomationReceiving(false);
    }
  };

  const handleBulkAutomationReceive = async () => {
    if (!checkedIds.length) {
      messageApi.warning('접수할 게시글을 선택하세요.');
      return;
    }

    const targetItems = items.filter((item) => checkedIds.includes(item.id));
    const receivableItems = targetItems.filter((item) => !getBoardPostAutomationReceiveError(item, dirtyDraftId));

    if (!receivableItems.length) {
      messageApi.warning('선택한 게시글 중 자동화 접수할 수 있는 항목이 없습니다.');
      return;
    }

    setAutomationReceiving(true);
    setAutomationReceiveError(null);

    const updatedItems = new Map<number, BoardPost>();
    const alreadyReceivedIds: number[] = [];
    const failedItems: Array<{ id: number; message: string }> = [];

    try {
      for (const item of receivableItems) {
        try {
          const result = await receiveBoardPostAutomation(item.id);
          updatedItems.set(result.item.id, result.item);

          if (result.alreadyReceived) {
            alreadyReceivedIds.push(item.id);
          }
        } catch (error) {
          failedItems.push({
            id: item.id,
            message: error instanceof Error ? error.message : '자동화 접수에 실패했습니다.',
          });
        }
      }

      if (updatedItems.size > 0) {
        setItems((previous) => previous.map((item) => updatedItems.get(item.id) ?? item));
      }

      setCheckedIds((previous) => previous.filter((id) => !updatedItems.has(id)));

      const receivedCount = updatedItems.size - alreadyReceivedIds.length;
      const summaryParts = [
        receivedCount > 0 ? `${receivedCount}건 접수` : null,
        alreadyReceivedIds.length > 0 ? `${alreadyReceivedIds.length}건 기존 접수` : null,
        failedItems.length > 0 ? `${failedItems.length}건 실패` : null,
      ].filter(Boolean);

      if (failedItems.length > 0) {
        messageApi.warning(`선택 접수 결과: ${summaryParts.join(', ')}.`);
      } else {
        messageApi.success(`선택한 게시글을 처리했습니다. ${summaryParts.join(', ')}.`);
      }

      if (selectedItem) {
        const selectedFailure = failedItems.find((entry) => entry.id === selectedItem.id);
        setAutomationReceiveError(selectedFailure?.message ?? null);
      }
    } finally {
      setAutomationReceiving(false);
    }
  };

  return (
    <Space direction="vertical" size={16} className="board-page">
      {contextHolder}
      <Card className="board-page__card" bordered={false}>
        <Flex justify="space-between" align="center" gap={16} wrap>
          <div>
            <Title level={4} className="board-page__title">
              Plan
            </Title>
            <Paragraph className="board-page__copy">
              마크다운 본문을 입력하고 즉시 프리뷰를 확인한 뒤 DB에 저장합니다.
            </Paragraph>
          </div>
          <Space wrap>
            <Button icon={<PlusOutlined />} onClick={handleCreateDraft}>
              새 글
            </Button>
            <Button
              type="primary"
              icon={<SaveOutlined />}
              loading={saving}
              disabled={isDraftLocked}
              onClick={() => {
                void handleSave();
              }}
            >
              저장
            </Button>
          </Space>
        </Flex>
      </Card>

      {errorMessage ? (
        <Card className="board-page__card" bordered={false}>
          <Text type="danger">{errorMessage}</Text>
        </Card>
      ) : null}

      <div className="board-page__grid">
        <Card
          title={`게시글 목록 (${items.length})`}
          className={`board-page__card board-page__list-card${
            showMobileDetailOnly ? ' board-page__list-card--mobile-hidden' : ''
          }`}
          bordered={false}
          extra={
            <Space size={8} wrap>
              {loading ? <Spin size="small" /> : null}
              <Text type="secondary" className="board-page__bulk-count">
                선택 {checkedReceivableCount}건
              </Text>
              <Checkbox
                indeterminate={partiallyChecked}
                checked={allReceivableChecked}
                disabled={!receivableIds.length}
                onChange={(event) => {
                  setCheckedIds((previous) => {
                    if (event.target.checked) {
                      return Array.from(new Set([...previous, ...receivableIds]));
                    }

                    return previous.filter((id) => !receivableIdSet.has(id));
                  });
                }}
              >
                대기 전체
              </Checkbox>
              <Button
                icon={<CheckSquareOutlined />}
                loading={automationReceiving}
                disabled={!checkedReceivableCount}
                onClick={() => {
                  void handleBulkAutomationReceive();
                }}
              >
                선택 접수
              </Button>
            </Space>
          }
        >
          {loading ? (
            <div className="board-page__loading">
              <Spin />
            </div>
          ) : items.length ? (
            <List
              dataSource={items}
              renderItem={(item) => (
                  <List.Item
                    className={item.id === selectedId ? 'board-page__list-item is-active' : 'board-page__list-item'}
                    onClick={() => {
                      setSelectedId(item.id);
                      if (isMobileViewport) {
                        setMobileDetailOpen(true);
                      }
                    }}
                  >
                  <List.Item.Meta
                    avatar={
                      <Checkbox
                        checked={checkedIds.includes(item.id)}
                        disabled={Boolean(getBoardPostAutomationReceiveError(item, dirtyDraftId))}
                        onClick={(event) => {
                          event.stopPropagation();
                        }}
                        onChange={(event) => {
                          setCheckedIds((previous) =>
                            event.target.checked
                              ? Array.from(new Set([...previous, item.id]))
                              : previous.filter((checkedId) => checkedId !== item.id),
                          );
                        }}
                      />
                    }
                    title={
                      <Flex justify="space-between" align="center" gap={8}>
                        <Flex align="center" gap={8} className="board-page__list-title">
                          <FileTextOutlined className="board-page__list-icon" />
                          <Text strong>{item.title}</Text>
                        </Flex>
                        <Space size={6} wrap>
                          {item.id === dirtyDraftId ? <Tag color="warning">저장 필요</Tag> : null}
                          <Tag color={item.automationReceivedAt || item.automationPlanItemId ? 'processing' : 'default'}>
                            {item.automationReceivedAt || item.automationPlanItemId ? '접수완료' : '대기'}
                          </Tag>
                        </Space>
                      </Flex>
                    }
                    description={
                      <Space direction="vertical" size={4}>
                        <Text type="secondary" className="board-page__list-preview">
                          {item.preview || '본문 미리보기가 없습니다.'}
                        </Text>
                        <Text type="secondary">수정 {formatDateTime(item.updatedAt)}</Text>
                      </Space>
                    }
                  />
                </List.Item>
              )}
            />
          ) : (
            <Empty description="등록된 게시글이 없습니다." />
          )}
        </Card>

        <div
          className={`board-page__editor-column${
            isMobileViewport && !mobileDetailOpen ? ' board-page__editor-column--mobile-hidden' : ''
          }`}
        >
          <Card
            title={draft.id ? `게시글 #${draft.id}` : '새 게시글'}
            className="board-page__card board-page__editor-card"
            bordered={false}
            extra={
              <Space wrap>
                {isMobileViewport && mobileDetailOpen ? (
                  <Button
                    icon={<ArrowLeftOutlined />}
                    onClick={() => {
                      setMobileDetailOpen(false);
                    }}
                  >
                    목록
                  </Button>
                ) : null}
                {draft.id ? <Tag color={automationStatus.color}>{automationStatus.label}</Tag> : null}
                {draft.id && selectedItem?.automationPlanItemId ? (
                  <Button
                    href={`/plans/all?planId=${selectedItem.automationPlanItemId}`}
                    target="_blank"
                    rel="noreferrer"
                  >
                    연결자동화
                  </Button>
                ) : null}
                {draft.id ? (
                  <Button
                    icon={<PlayCircleOutlined />}
                    loading={automationReceiving}
                    disabled={automationReceived && !automationReceiveError}
                    onClick={() => {
                      void handleAutomationReceive();
                    }}
                  >
                    {automationReceived ? '자동화 접수됨' : automationReceiveError ? '접수 재시도' : '자동화 접수'}
                  </Button>
                ) : null}
                {draft.id ? (
                  <Button
                    danger
                    icon={<DeleteOutlined />}
                    loading={deleting}
                    disabled={isDraftLocked}
                    onClick={() => {
                      void handleDelete();
                    }}
                  >
                    삭제
                  </Button>
                ) : null}
              </Space>
            }
          >
            <Space direction="vertical" size={16} className="board-page__editor">
              <Input
                size="large"
                placeholder="제목을 입력하세요"
                value={draft.title}
                readOnly={isDraftLocked}
                onChange={(event) => {
                  setDraft((previous) => ({
                    ...previous,
                    title: event.target.value,
                  }));
                }}
              />
              <Flex gap={8} wrap>
                <Tag color={automationStatus.color}>{automationStatus.label}</Tag>
                {automationStatus.description ? <Text type="secondary">{automationStatus.description}</Text> : null}
              </Flex>
              <div className="board-page__automation-field">
                <Text strong>자동화 처리</Text>
                {automationReceived ? (
                  <div className="board-page__automation-readonly" aria-readonly="true">
                    <Text>{automationTypeLabel}</Text>
                    <Tag color="processing">접수 후 읽기전용</Tag>
                  </div>
                ) : (
                    <Select
                      className="board-page__automation-select"
                      value={draft.automationType}
                    options={BOARD_AUTOMATION_TYPE_OPTIONS}
                    popupClassName="board-page__automation-select-popup"
                    getPopupContainer={(triggerNode) => triggerNode.parentElement ?? document.body}
                      disabled={isDraftLocked}
                      onChange={(automationType) => {
                        setDraft((previous) => ({
                          ...previous,
                        automationType,
                      }));
                    }}
                  />
                )}
              </div>
              <div className={`board-page__editor-frame${contentExpanded ? ' board-page__editor-frame--expanded' : ''}`}>
                {contentExpanded ? (
                  <Flex justify="space-between" align="center" gap={12} className="board-page__editor-toolbar">
                    <Text strong>본문 전체화면</Text>
                    <Space size={8}>
                      <Button
                        size="small"
                        icon={<CopyOutlined />}
                        aria-label="본문 복사"
                        title="본문 복사"
                        onClick={() => {
                          void handleCopyContent();
                        }}
                      >
                        복사
                      </Button>
                      <Button
                        size="small"
                        icon={<CompressOutlined />}
                        aria-label="본문 최대화 해제"
                        onClick={() => {
                          setContentExpanded(false);
                        }}
                      >
                        닫기
                      </Button>
                    </Space>
                  </Flex>
                ) : null}
                <Segmented
                  className="board-page__mobile-toggle"
                  options={[
                    { label: '편집', value: 'edit', icon: <FileTextOutlined /> },
                    { label: '미리보기', value: 'preview', icon: <EyeOutlined /> },
                  ]}
                  value={mobileView}
                  onChange={(value) => {
                    setMobileView(value as 'edit' | 'preview');
                  }}
                />
                <Flex justify="space-between" align="center" gap={8}>
                  <Text type="secondary">본문</Text>
                  <Space size={8}>
                    <Button
                      icon={<CopyOutlined />}
                      aria-label="본문 복사"
                      title="본문 복사"
                      onClick={() => {
                        void handleCopyContent();
                      }}
                    />
                    <Button
                      icon={contentExpanded ? <CompressOutlined /> : <ExpandOutlined />}
                      aria-label={contentExpanded ? '본문 최대화 해제' : '본문 최대화'}
                      title={contentExpanded ? '본문 최대화 해제' : '본문 최대화'}
                      onClick={() => {
                        setContentExpanded((previous) => !previous);
                      }}
                    />
                  </Space>
                </Flex>
                <div
                  className={`board-page__preview-grid${contentExpanded ? ' board-page__preview-grid--expanded' : ''}`}
                >
                  <div
                    className={`board-page__pane${mobileView === 'preview' ? ' board-page__pane--mobile-hidden' : ''}${
                      contentExpanded ? ' board-page__pane--expanded' : ''
                    }`}
                  >
                    <TextArea
                      value={draft.content}
                      placeholder={'# 제목\n\n마크다운 본문을 입력하세요.\n\n- 목록\n- 코드블록\n- 링크'}
                      readOnly={isDraftLocked}
                      onChange={(event) => {
                        setDraft((previous) => ({
                          ...previous,
                          content: event.target.value,
                        }));
                      }}
                      className={`board-page__textarea${contentExpanded ? ' board-page__textarea--expanded' : ''}`}
                    />
                  </div>
                  <div
                    className={`board-page__pane${mobileView === 'edit' ? ' board-page__pane--mobile-hidden' : ''}${
                      contentExpanded ? ' board-page__pane--expanded' : ''
                    }`}
                  >
                    <div className={`board-page__preview${contentExpanded ? ' board-page__preview--expanded' : ''}`}>
                      <div className="board-page__preview-content">
                      {draft.content.trim() ? (
                        <MarkdownPreviewContent content={draft.content} />
                      ) : (
                        <Empty description="미리보기할 본문이 없습니다." image={Empty.PRESENTED_IMAGE_SIMPLE} />
                      )}
                      </div>
                    </div>
                  </div>
                </div>
                {isDraftLocked ? (
                  <Text type="secondary">자동화 접수된 작업메모는 게시판에서 수정하거나 삭제할 수 없습니다.</Text>
                ) : null}
              </div>
            </Space>
          </Card>
        </div>
      </div>
    </Space>
  );
}
