./knowledge-base/frontend/src/pages/UploadPage.tsx

import { useState } from "react";
import { useMutation, useQuery } from "@tanstack/react-query";
import {
  Container,
  Box,
  Typography,
  TextField,
  Button,
  Chip,
  AppBar,
  Toolbar,
  Paper,
  Alert,
  CircularProgress,
  LinearProgress,
  ToggleButtonGroup,
  ToggleButton,
  Autocomplete,
} from "@mui/material";
import { DocumentGenreSelector } from "../components/DocumentGenreSelector";
import {
  Upload as UploadIcon,
  Home as HomeIcon,
  Image as ImageIcon,
  PictureAsPdf as PdfIcon,
} from "@mui/icons-material";
import { useNavigate } from "react-router-dom";
import { bulkUpload, uploadPdf, fetchPrograms } from "../api/client";
import type {
  BulkUploadRequest,
  BookMetadata,
  PageMetadata,
  PdfUploadUrlRequest,
  ProgramMaster,
} from "../types";
import { EraSelector } from "../components/EraSelector";

type UploadMode = "image" | "pdf";

export default function UploadPage() {
  const navigate = useNavigate();
  const [uploadMode, setUploadMode] = useState<UploadMode>("pdf");
  // ドキュメントIDはUUIDで自動生成
  const [documentId, setDocumentId] = useState(() => crypto.randomUUID());
  const [title, setTitle] = useState("");

  // 時代設定モード: "manual" = 手動設定、"auto" = 自動設定(AI判定)
  const [eraMode, setEraMode] = useState<"manual" | "auto">("manual");
  const [eraLabels, setEraLabels] = useState<string[]>([]);

  const [documentGenre, setDocumentGenre] = useState("");
  const [selectedPrograms, setSelectedPrograms] = useState<string[]>([]);
  const [tags, setTags] = useState("");
  const [files, setFiles] = useState<File[]>([]);
  const [pdfProgress, setPdfProgress] = useState<number>(0);
  const [pdfStatus, setPdfStatus] = useState<string>("");

  // 番組マスタを読み込み
  const { data: programList = [] } = useQuery<ProgramMaster[]>({
    queryKey: ["programs"],
    queryFn: fetchPrograms,
    staleTime: 5 * 60 * 1000,
  });

  // 画像一括アップロード処理
  const imageMutation = useMutation({
    mutationFn: (params: BulkUploadRequest) => bulkUpload(params),
    onSuccess: (data) => {
      alert(
        `アップロード完了: 成功 ${data.success_count}件 / 失敗 ${data.failure_count}件`,
      );
      resetForm();
    },
    onError: (error) => {
      console.error("Upload error:", error);
      alert("アップロードに失敗しました");
    },
  });

  // PDFアップロード処理
  const pdfMutation = useMutation({
    mutationFn: async (params: {
      request: PdfUploadUrlRequest;
      file: File;
    }) => {
      setPdfStatus("PDFをアップロード中...");
      setPdfProgress(0);
      const result = await uploadPdf(params.request, params.file, (percent) => {
        setPdfProgress(percent);
        setPdfStatus(`PDFをアップロード中... ${percent}%`);
      });
      setPdfStatus(
        "✅ アップロード完了。バックグラウンドでページ分割・解析が開始されます。",
      );
      return result;
    },
    onSuccess: () => {
      setTimeout(() => {
        resetForm();
      }, 3000);
    },
    onError: (error) => {
      console.error("PDF upload error:", error);
      setPdfStatus("❌ アップロードに失敗しました");
      alert("PDFのアップロードに失敗しました");
    },
  });

  const resetForm = () => {
    setFiles([]);
    setDocumentId(crypto.randomUUID());
    setTitle("");
    setEraMode("manual");
    setEraLabels([]);
    setDocumentGenre("");
    setSelectedPrograms([]);
    setTags("");
    setPdfProgress(0);
    setPdfStatus("");
  };

  const buildBookMetadata = (): BookMetadata => ({
    title,
    era_labels: eraMode === "auto" ? [] : eraLabels,
    document_genre: documentGenre,
    programs: selectedPrograms,
  });

  const buildPageMetadata = (): Partial<PageMetadata> => ({
    tags: tags
      .split(",")
      .map((t) => t.trim())
      .filter(Boolean),
  });

  const validateForm = () => {
    const eraOk = eraMode === "auto" || eraLabels.length > 0;
    if (!title || !documentGenre || !eraOk) {
      alert(
        "タイトル、資料ジャンル、時代タグ(自動設定の場合は不要)は必須です",
      );
      return false;
    }
    if (files.length === 0) {
      alert("ファイルを選択してください");
      return false;
    }
    return true;
  };

  const handleImageUpload = async () => {
    if (!validateForm()) return;

    const items = await Promise.all(
      files.map(async (file, index) => {
        const base64 = await fileToBase64(file);
        return {
          document_id: documentId,
          page_number: index + 1,
          image_data: base64,
        };
      }),
    );

    const request: BulkUploadRequest = {
      book_metadata: buildBookMetadata(),
      items,
      metadata: buildPageMetadata(),
    };

    imageMutation.mutate(request);
  };

  const handlePdfUpload = () => {
    if (!validateForm()) return;
    if (
      files[0].type !== "application/pdf" &&
      !files[0].name.toLowerCase().endsWith(".pdf")
    ) {
      alert("PDFファイルを選択してください");
      return;
    }

    const request: PdfUploadUrlRequest = {
      document_id: documentId,
      filename: files[0].name,
      book_metadata: buildBookMetadata(),
    };

    pdfMutation.mutate({ request, file: files[0] });
  };

  const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    if (event.target.files) {
      setFiles(Array.from(event.target.files));
    }
  };

  const isLoading = imageMutation.isPending || pdfMutation.isPending;

  return (
    <>
      {/* ヘッダー */}
      <AppBar position="static">
        <Toolbar>
          <Button
            color="inherit"
            startIcon={<HomeIcon />}
            onClick={() => navigate("/")}
          >
            ホーム
          </Button>
          <Box
            component="img"
            src="/img/fav.png"
            alt="ロゴ"
            sx={{ height: 28, width: 28, mr: 1, ml: 1, borderRadius: 1 }}
          />
          <Typography variant="h6" sx={{ flexGrow: 1 }}>
            時代考証システム - アップロード
          </Typography>
        </Toolbar>
      </AppBar>

      {/* メインコンテンツ */}
      <Container maxWidth="md" sx={{ mt: 4, mb: 4 }}>
        <Paper sx={{ p: 4 }}>
          <Typography variant="h5" gutterBottom>
            資料アップロード
          </Typography>

          {/* アップロードモード切り替え */}
          <Box sx={{ mb: 3 }}>
            <ToggleButtonGroup
              value={uploadMode}
              exclusive
              onChange={(_, value) => {
                if (value) {
                  setUploadMode(value);
                  setFiles([]);
                }
              }}
              aria-label="アップロードモード"
            >
              <ToggleButton value="image" aria-label="画像">
                <ImageIcon sx={{ mr: 1 }} />
                画像(複数枚)
              </ToggleButton>
              <ToggleButton value="pdf" aria-label="PDF">
                <PdfIcon sx={{ mr: 1 }} />
                PDFファイル(1冊)
              </ToggleButton>
            </ToggleButtonGroup>
          </Box>

          <Alert severity="info" sx={{ mb: 3 }}>
            {uploadMode === "image"
              ? "※ 選択した全画像に同じメタデータが適用されます"
              : "※ PDFを1ファイル選択してください。各ページが自動的に分割・解析されます。ページ番号はPDF内のページ順に記録されます。"}
          </Alert>

          <Box sx={{ display: "flex", flexDirection: "column", gap: 3 }}>
            {/* タイトル */}
            <TextField
              fullWidth
              label="タイトル(書籍タイトル)"
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              placeholder="例: 昭和の生活写真集"
              required
            />

            {/* 時代タグ(複数可) */}
            <Box>
              <Typography variant="subtitle2" gutterBottom>
                時代タグ <span style={{ color: "red" }}>*</span>
              </Typography>
              {/* 手動設定 / 自動設定 トグル */}
              <ToggleButtonGroup
                value={eraMode}
                exclusive
                size="small"
                onChange={(_, v) => {
                  if (v) setEraMode(v);
                }}
                sx={{ mb: 1.5 }}
              >
                <ToggleButton value="manual">手動設定</ToggleButton>
                <ToggleButton value="auto">自動設定</ToggleButton>
              </ToggleButtonGroup>
              <Typography
                variant="caption"
                color="text.secondary"
                display="block"
                sx={{ mb: 1 }}
              >
                {eraMode === "auto"
                  ? "AIがページごとに時代を自動判定します。時代タグの入力は不要です。"
                  : "室町以前~平成~の9開期から該当するものを選んでください。複数選択可能です。"}
              </Typography>

              <EraSelector
                value={eraLabels}
                onChange={setEraLabels}
                disabled={eraMode === "auto"}
              />
            </Box>

            {/* 資料ジャンル */}
            <Box>
              <Typography variant="subtitle2" gutterBottom>
                資料ジャンル <span style={{ color: "red" }}>*</span>
              </Typography>
              <DocumentGenreSelector
                value={documentGenre}
                onChange={setDocumentGenre}
              />
            </Box>

            {/* タグ */}
            <TextField
              fullWidth
              label="タグ(カンマ区切り)"
              value={tags}
              onChange={(e) => setTags(e.target.value)}
              placeholder="例: 台所, 家電, レトロ"
            />

            {/* 番組名 */}
            <Autocomplete
              multiple
              disableCloseOnSelect
              options={programList.map((p) => p.name)}
              value={selectedPrograms}
              onChange={(_, newValue) => setSelectedPrograms(newValue)}
              renderInput={(params) => (
                <TextField
                  {...params}
                  label="番組名(任意)"
                  placeholder="番組を選択してください"
                />
              )}
              renderTags={(value, getTagProps) =>
                value.map((option, index) => (
                  <Chip
                    label={option}
                    size="small"
                    {...getTagProps({ index })}
                    key={option}
                  />
                ))
              }
              noOptionsText="番組が登録されていません"
            />

            {/* ファイル選択 */}
            <Box>
              <Button
                variant="outlined"
                component="label"
                fullWidth
                sx={{
                  height: 56,
                  borderStyle: uploadMode === "pdf" ? "dashed" : "solid",
                }}
                disabled={isLoading}
              >
                {uploadMode === "image"
                  ? `画像を選択 (${files.length}件)`
                  : files.length > 0
                    ? `選択済み: ${files[0].name}`
                    : "PDFを選択"}
                <input
                  type="file"
                  hidden
                  multiple={uploadMode === "image"}
                  accept={
                    uploadMode === "image" ? "image/*" : "application/pdf,.pdf"
                  }
                  onChange={handleFileChange}
                />
              </Button>
              {files.length > 0 && uploadMode === "image" && (
                <Typography
                  variant="body2"
                  color="text.secondary"
                  sx={{ mt: 1 }}
                >
                  選択されたファイル: {files.map((f) => f.name).join(", ")}
                </Typography>
              )}
            </Box>

            {/* PDFアップロード進捗 */}
            {uploadMode === "pdf" && pdfMutation.isPending && (
              <Box>
                <LinearProgress
                  variant="determinate"
                  value={pdfProgress}
                  sx={{ mb: 1 }}