'use client';

import { useActionState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { Field } from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import { Modal } from '@/components/ui/modal';
import { RadioGroup } from '@/components/ui/radio-group';
import { Select } from '@/components/ui/select';
import { useFeedback } from '@/app/_hooks/use-feedback';
import {
  BOARD_CATEGORY_OPTIONS,
  formatBoardCategoryLabel,
  formatOptionalValue,
  type BoardPost,
  type BoardType,
} from '@/lib/domain/board-post';
import {
  CONTENT_MAX_LENGTH,
  TITLE_MAX_LENGTH,
} from '@/lib/domain/board-post-form';
import { BOARD_TYPE_OPTIONS } from '@/lib/domain/board-post-query';
import {
  INITIAL_BOARD_POST_FORM_STATE,
  createBoardPostAction,
  updateBoardPostAction,
} from '../_actions';
import { BoardAttachmentField } from './board-attachment-field';
import { BoardContentField } from './board-content-field';

interface BoardPostFormModalProps {
  boardType: BoardType;
  mode: 'create' | 'edit';
  /** 수정 모드의 기존 값. 등록 모드는 넘기지 않는다. */
  post?: BoardPost;
  onClose: () => void;
}

const FORM_ID = 'board-post-form';

const PINNED_OPTIONS = [
  { value: 'N', label: '사용안함' },
  { value: 'Y', label: '사용' },
];
const VISIBILITY_OPTIONS = [
  { value: 'Y', label: '노출' },
  { value: 'N', label: '미노출' },
];
const PUSH_OPTIONS = [
  { value: 'Y', label: '발송' },
  { value: 'N', label: '미발송' },
];

const BOARD_TITLES: Record<BoardType, string> = {
  notice: '공지사항',
  inquiry: '1:1문의',
  faq: 'FAQ',
};

/**
 * 공지사항·FAQ의 등록/수정 팝업 — 시안 A_BOA_007_p·008_p(공지사항), 015_p·016_p(FAQ).
 *
 * 네 시안이 같은 폼의 변형이라 한 컴포넌트가 게시판 종류(`boardType`)와 모드(`mode`)로 분기한다.
 * 게시판별 차이는 두 가지뿐이다 — 공지사항에만 상단고정·노출기간·앱푸쉬가, FAQ에만 유형이 있다.
 *
 * **수정 시 구분은 읽기 전용이다**(시안 ①). 값 자체를 제출하지 않고, Server Action도 수정
 * 경로에서는 구분을 검증하지 않는다 — 직접 POST로 다른 값을 보내도 반영되지 않는다.
 *
 * 첨부파일이 있어 폼은 multipart로 제출된다(Server Action은 이를 자동으로 처리한다).
 * 저장 버튼은 footer에서 `form={FORM_ID}`로 연결한다 — 네이티브 HTML의 `form` 속성은 버튼이
 * DOM상 form의 자손이 아니어도 같은 문서 안에서 id만 일치하면 그 form을 제출한다.
 */
export function BoardPostFormModal({
  boardType,
  mode,
  post,
  onClose,
}: BoardPostFormModalProps) {
  const { showToast } = useFeedback();
  const isCreate = mode === 'create';

  const [state, formAction, isPending] = useActionState(
    isCreate ? createBoardPostAction : updateBoardPostAction,
    INITIAL_BOARD_POST_FORM_STATE
  );

  useEffect(() => {
    if (state.status === 'success') {
      showToast({
        variant: 'success',
        message: isCreate ? '게시물을 등록했습니다.' : '게시물을 수정했습니다.',
      });
      onClose();
    }
  }, [state, showToast, onClose, isCreate]);

  const errors = state.status === 'error' ? (state.errors ?? {}) : {};
  const typeOptions = BOARD_TYPE_OPTIONS[boardType];
  const hasNoticeOnlyFields = boardType === 'notice';

  return (
    <Modal
      title={`${BOARD_TITLES[boardType]} ${isCreate ? '신규 등록' : '수정'}`}
      onClose={onClose}
      footer={
        <>
          <Button type="button" variant="ghost" onClick={onClose}>
            취소
          </Button>
          <Button
            type="submit"
            form={FORM_ID}
            variant="primary"
            disabled={isPending}
          >
            {isPending ? '저장 중...' : isCreate ? '등록' : '수정'}
          </Button>
        </>
      }
    >
      <form id={FORM_ID} action={formAction} className="flex flex-col gap-4">
        <input type="hidden" name="boardType" value={boardType} />
        {!isCreate && post && <input type="hidden" name="id" value={post.id} />}

        <p className="text-right text-body-sm text-danger">
          * 는 필수 항목입니다.
        </p>

        <Field label={isCreate ? '구분 *' : '구분'}>
          {isCreate ? (
            <Select name="categoryCode" defaultValue={BOARD_CATEGORY_OPTIONS[0].value}>
              {BOARD_CATEGORY_OPTIONS.map((option) => (
                <option key={option.value} value={option.value}>
                  {option.label}
                </option>
              ))}
            </Select>
          ) : (
            <Input
              value={formatBoardCategoryLabel(post?.categoryCode ?? null)}
              readOnly
            />
          )}
        </Field>
        <FieldError message={errors.categoryCode} />

        {typeOptions.length > 0 && (
          <>
            <Field label="유형 *">
              <Select name="typeCode" defaultValue={post?.typeCode ?? ''}>
                <option value="">선택</option>
                {typeOptions.map((option) => (
                  <option key={option.value} value={option.value}>
                    {option.label}
                  </option>
                ))}
              </Select>
            </Field>
            <FieldError message={errors.typeCode} />
          </>
        )}

        <Field label="제목 *">
          <Input
            type="text"
            name="title"
            defaultValue={post?.title ?? ''}
            maxLength={TITLE_MAX_LENGTH}
            placeholder="제목을 입력하세요."
          />
        </Field>
        <FieldError message={errors.title} />

        <BoardContentField
          name="content"
          label="내용 *"
          defaultValue={post?.content ?? ''}
          maxLength={CONTENT_MAX_LENGTH}
          placeholder="내용을 입력하세요."
        />
        <FieldError message={errors.content} />

        <BoardAttachmentField attachmentId={post?.attachmentId} />

        {hasNoticeOnlyFields && (
          <>
            <Field label="상단고정">
              <RadioGroup
                name="isPinned"
                options={PINNED_OPTIONS}
                defaultValue={post?.isPinned ? 'Y' : 'N'}
              />
            </Field>

            <Field label="노출기간">
              <div className="flex items-center gap-2">
                <Input
                  type="date"
                  name="startDate"
                  defaultValue={post?.startDate ?? ''}
                  aria-label="게시시작일시"
                />
                <span className="text-foreground-muted">~</span>
                <Input
                  type="date"
                  name="endDate"
                  defaultValue={post?.endDate ?? ''}
                  aria-label="게시종료일시"
                />
              </div>
            </Field>
            <FieldError message={errors.startDate} />
            <FieldError message={errors.endDate} />
          </>
        )}

        <Field label="사용여부 *">
          <RadioGroup
            name="isVisible"
            options={VISIBILITY_OPTIONS}
            defaultValue={post?.isVisible === false ? 'N' : 'Y'}
          />
        </Field>

        {hasNoticeOnlyFields && (
          <Field label="앱푸쉬 설정 *">
            <RadioGroup
              name="isPushEnabled"
              options={PUSH_OPTIONS}
              defaultValue={post?.isPushEnabled === false ? 'N' : 'Y'}
            />
          </Field>
        )}

        {!isCreate && post && (
          <Field label="작성자 / 작성일">
            <div className="flex items-center gap-2">
              <Input value={formatOptionalValue(post.authorName)} readOnly />
              <Input value={formatOptionalValue(post.createdAt)} readOnly />
            </div>
          </Field>
        )}

        {state.status === 'error' && state.message && (
          <p className="text-body-sm text-danger">{state.message}</p>
        )}
      </form>
    </Modal>
  );
}

/** 필드 하단 오류 문구. 값이 없으면 아무것도 그리지 않아 레이아웃을 차지하지 않는다. */
export function FieldError({ message }: { message?: string }) {
  if (!message) {
    return null;
  }
  return <p className="text-body-sm text-danger">{message}</p>;
}
