import { ArrowLeft, CheckCircle2, Send } from 'lucide-react';
import { useRef, useState } from 'react';

import type { ProfileFeedbackEvidenceItemInput } from '../../../packages/shared/src/contracts/runtime';
import { PlatformActionButton } from '../common/PlatformActionButton';
import { PlatformFieldLabel } from '../common/PlatformFieldLabel';
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
import { PlatformSubpanel } from '../common/PlatformSubpanel';
import { PlatformTextField } from '../common/PlatformTextField';
import { PlatformUploadPreviewCard } from '../common/PlatformUploadPreviewCard';
import { PlatformUploadTile } from '../common/PlatformUploadTile';

const MIN_FEEDBACK_DESCRIPTION_LENGTH = 10;
const MAX_FEEDBACK_DESCRIPTION_LENGTH = 200;
const MAX_FEEDBACK_EVIDENCE_COUNT = 4;
const MAX_CONTACT_PHONE_LENGTH = 40;
const MAX_FEEDBACK_EVIDENCE_BYTES = 1_048_576;
const MAX_FEEDBACK_EVIDENCE_TOTAL_BYTES = 4_194_304;

export type PlatformFeedbackPayload = {
  description: string;
  contactPhone?: string | null;
  evidenceItems: ProfileFeedbackEvidenceItemInput[];
};

export type PlatformFeedbackViewProps = {
  onBack: () => void;
  onSubmit?: (payload: PlatformFeedbackPayload) => void | Promise<unknown>;
};

type EvidencePreview = {
  id: string;
  fileName: string;
  contentType: string;
  sizeBytes: number;
  dataUrl: string;
};

function buildEvidencePreviewId(file: File, index: number) {
  return `${file.name}:${file.size}:${file.lastModified}:${index}`;
}

function readFileAsDataUrl(file: File) {
  return new Promise<string>((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      if (typeof reader.result === 'string') {
        resolve(reader.result);
      } else {
        reject(new Error('图片读取失败'));
      }
    };
    reader.onerror = () => reject(new Error('图片读取失败'));
    reader.readAsDataURL(file);
  });
}

export function PlatformFeedbackView({
  onBack,
  onSubmit,
}: PlatformFeedbackViewProps) {
  const evidenceInputRef = useRef<HTMLInputElement | null>(null);
  const [description, setDescription] = useState('');
  const [contactPhone, setContactPhone] = useState('');
  const [evidencePreviews, setEvidencePreviews] = useState<EvidencePreview[]>(
    [],
  );
  const [error, setError] = useState<string | null>(null);
  const [notice, setNotice] = useState<string | null>(null);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [submitted, setSubmitted] = useState(false);

  const descriptionLength = description.length;

  const showTemporaryNotice = (message: string) => {
    setNotice(message);
    window.setTimeout(() => setNotice(null), 1600);
  };

  const updateDescription = (value: string) => {
    setDescription(value.slice(0, MAX_FEEDBACK_DESCRIPTION_LENGTH));
    setError(null);
    setSubmitted(false);
  };

  const updateContactPhone = (value: string) => {
    setContactPhone(value.slice(0, MAX_CONTACT_PHONE_LENGTH));
    setError(null);
    setSubmitted(false);
  };

  const openEvidencePicker = () => {
    evidenceInputRef.current?.click();
  };

  const addEvidenceFiles = (files: FileList | null) => {
    const selectedFiles = files ? Array.from(files) : [];
    if (evidenceInputRef.current) {
      evidenceInputRef.current.value = '';
    }
    if (selectedFiles.length === 0) {
      return;
    }

    if (selectedFiles.some((file) => !file.type.startsWith('image/'))) {
      setError('反馈凭证只支持图片类型');
      return;
    }
    const remainingCount =
      MAX_FEEDBACK_EVIDENCE_COUNT - evidencePreviews.length;
    if (remainingCount <= 0 || selectedFiles.length > remainingCount) {
      setError('最多上传四张凭证');
    }

    const nextFiles = selectedFiles.slice(0, Math.max(remainingCount, 0));
    if (nextFiles.length === 0) {
      return;
    }

    if (nextFiles.some((file) => file.size > MAX_FEEDBACK_EVIDENCE_BYTES)) {
      setError('单张反馈凭证不能超过 1MB');
      return;
    }
    const currentTotalBytes = evidencePreviews.reduce(
      (total, preview) => total + preview.sizeBytes,
      0,
    );
    const nextTotalBytes = nextFiles.reduce(
      (total, file) => total + file.size,
      currentTotalBytes,
    );
    if (nextTotalBytes > MAX_FEEDBACK_EVIDENCE_TOTAL_BYTES) {
      setError('反馈凭证总大小不能超过 4MB');
      return;
    }

    Promise.all(
      nextFiles.map(async (file, index) => ({
        id: buildEvidencePreviewId(file, evidencePreviews.length + index),
        fileName: file.name,
        contentType: file.type,
        sizeBytes: file.size,
        dataUrl: await readFileAsDataUrl(file),
      })),
    )
      .then((nextPreviews) => {
        setEvidencePreviews((currentPreviews) => [
          ...currentPreviews,
          ...nextPreviews,
        ]);
        setError(null);
        setSubmitted(false);
      })
      .catch((readError: unknown) => {
        setError(
          readError instanceof Error ? readError.message : '图片读取失败',
        );
      });
  };

  const removeEvidencePreview = (id: string) => {
    setEvidencePreviews((currentPreviews) =>
      currentPreviews.filter((preview) => preview.id !== id),
    );
    setError(null);
    setSubmitted(false);
  };

  const submitFeedback = () => {
    if (isSubmitting) {
      return;
    }

    const trimmedDescription = description.trim();
    const trimmedContactPhone = contactPhone.trim();
    if (trimmedDescription.length < MIN_FEEDBACK_DESCRIPTION_LENGTH) {
      setError('请填写10个字以上的问题描述');
      setSubmitted(false);
      return;
    }
    if (trimmedDescription.length > MAX_FEEDBACK_DESCRIPTION_LENGTH) {
      setError('问题描述不能超过 200 字');
      setSubmitted(false);
      return;
    }
    if (trimmedContactPhone.length > MAX_CONTACT_PHONE_LENGTH) {
      setError('联系电话不能超过 40 字');
      setSubmitted(false);
      return;
    }
    if (evidencePreviews.length > MAX_FEEDBACK_EVIDENCE_COUNT) {
      setError('最多上传四张凭证');
      setSubmitted(false);
      return;
    }

    setIsSubmitting(true);
    setError(null);
    void Promise.resolve(
      onSubmit?.({
        description: trimmedDescription,
        contactPhone: trimmedContactPhone || null,
        evidenceItems: evidencePreviews.map((preview) => ({
          fileName: preview.fileName,
          contentType: preview.contentType,
          sizeBytes: preview.sizeBytes,
          dataUrl: preview.dataUrl,
        })),
      }),
    )
      .then(() => setSubmitted(true))
      .catch((submitError: unknown) => {
        setSubmitted(false);
        setError(
          submitError instanceof Error ? submitError.message : '提交失败',
        );
      })
      .finally(() => setIsSubmitting(false));
  };

  return (
    <div className="platform-page-stage platform-remap-surface min-h-0 flex-1 overflow-y-auto text-[var(--platform-text-strong)]">
      <div className="mx-auto flex min-h-full w-full max-w-[30rem] flex-col px-4 pb-6 pt-4">
        <header className="flex shrink-0 items-center gap-3 pb-3">
          <PlatformActionButton
            onClick={onBack}
            aria-label="返回我的页签"
            tone="ghost"
            shape="pill"
            size="xs"
            className="h-10 w-10 shrink-0 p-0"
          >
            <ArrowLeft className="h-[1.125rem] w-[1.125rem]" />
          </PlatformActionButton>
          <div className="min-w-0 text-base font-black text-[var(--platform-text-strong)]">
            帮助与反馈
          </div>
        </header>

        <main className="flex flex-1 flex-col gap-3">
          <div className="text-sm font-semibold text-[var(--platform-text-soft)]">
            反馈问题
          </div>

          <PlatformSubpanel radius="md">
            <label
              htmlFor="profile-feedback-description"
              className="block"
            >
              <PlatformFieldLabel
                variant="form"
                className="mb-0 text-base font-semibold"
              >
                问题描述
              </PlatformFieldLabel>
            </label>
            <PlatformTextField
              variant="textarea"
              id="profile-feedback-description"
              value={description}
              maxLength={MAX_FEEDBACK_DESCRIPTION_LENGTH}
              onChange={(event) => updateDescription(event.target.value)}
              placeholder="请填写10个字以上的问题描述以便我们提供更好的帮助，温馨提醒您请勿填写身份证号等个人隐私信息。"
              density="roomy"
              size="md"
              className="mt-3 min-h-[10.5rem] !rounded-none !border-0 !bg-transparent !px-0 !py-0 text-[var(--platform-text-strong)] placeholder:text-[var(--platform-text-soft)] focus:!bg-transparent focus:!ring-0"
            />
            <div className="text-right text-xs text-[var(--platform-text-soft)]">
              {descriptionLength}/{MAX_FEEDBACK_DESCRIPTION_LENGTH}
            </div>
          </PlatformSubpanel>

          <PlatformSubpanel radius="md">
            <div className="text-base font-semibold text-[var(--platform-text-strong)]">
              上传凭证(提供问题截图)
            </div>
            <div className="mt-4 flex flex-wrap gap-3">
              {evidencePreviews.map((preview) => (
                <PlatformUploadPreviewCard
                  key={preview.id}
                  imageSrc={preview.dataUrl}
                  imageAlt="反馈凭证预览"
                  removeLabel="移除上传凭证"
                  onRemove={() => removeEvidencePreview(preview.id)}
                />
              ))}
              {evidencePreviews.length < MAX_FEEDBACK_EVIDENCE_COUNT ? (
                <PlatformUploadTile
                  onClick={openEvidencePicker}
                  label="上传凭证"
                  hint="(最多四张)"
                />
              ) : null}
            </div>
            <input
              ref={evidenceInputRef}
              type="file"
              accept="image/*"
              multiple
              className="hidden"
              onChange={(event) => addEvidenceFiles(event.target.files)}
            />
          </PlatformSubpanel>

          <PlatformSubpanel radius="md">
            <label
              htmlFor="profile-feedback-phone"
              className="block"
            >
              <PlatformFieldLabel
                variant="form"
                className="mb-0 text-base font-semibold"
              >
                联系电话
              </PlatformFieldLabel>
            </label>
            <PlatformTextField
              id="profile-feedback-phone"
              type="tel"
              value={contactPhone}
              maxLength={MAX_CONTACT_PHONE_LENGTH}
              onChange={(event) => updateContactPhone(event.target.value)}
              placeholder="选填，如您填写则将会同步开发者与您联系"
              size="md"
              density="compact"
              className="mt-3 !rounded-none !border-0 !bg-transparent !px-0 !py-0 text-[var(--platform-text-strong)] placeholder:text-[var(--platform-text-soft)] focus:!bg-transparent focus:!ring-0"
            />
          </PlatformSubpanel>

          {error ? (
            <PlatformStatusMessage tone="error" surface="profile">
              {error}
            </PlatformStatusMessage>
          ) : null}
          {submitted ? (
            <PlatformStatusMessage tone="success" surface="profile">
              <CheckCircle2 className="h-4 w-4" />
              反馈已提交
            </PlatformStatusMessage>
          ) : null}
          {notice ? (
            <PlatformStatusMessage tone="info" surface="profile">
              {notice}
            </PlatformStatusMessage>
          ) : null}

          <PlatformActionButton
            fullWidth
            size="md"
            className="mt-2 h-12 text-base"
            onClick={submitFeedback}
            disabled={isSubmitting}
          >
            <Send className="h-4 w-4" />
            {isSubmitting ? '提交中' : '提交'}
          </PlatformActionButton>

          <PlatformActionButton
            tone="ghost"
            shape="pill"
            size="xs"
            onClick={() => showTemporaryNotice('反馈记录暂未开放')}
            className="self-center"
          >
            查看反馈与投诉记录
          </PlatformActionButton>
        </main>
      </div>
    </div>
  );
}
