// PDF export: đơn đề nghị (Noto Serif) + báo cáo mô tả trong một file khi xuất từ bản nháp.
// Dùng @react-pdf/renderer; tải xuống qua blob URL (không cần file-saver).

import {
  Document,
  Font,
  Page,
  StyleSheet,
  Text,
  View,
  pdf,
} from '@react-pdf/renderer';
import type {
  ApplicationFormState,
  Author,
  InitiativeDraft,
  InitiativeFormState,
  SupportStaff,
} from '@ump/shared';
import {
  ensureBanCamKet,
  ensureReferenceMaterialHonesty,
  ensureResearchDomesticHonesty,
  isBanCamKetComplete,
  isReferenceMaterialHonestyComplete,
  isResearchDomesticHonestyComplete,
  getFile,
  PDF_RENDER_DEADLINE_MS,
  withPromiseTimeout,
  displayDobStoredAsDdMm,
  formatVnDateFieldForDisplay,
} from '@ump/shared';

// ---------------------------------------------------------------------
// Font registration — Vietnamese support
//
// @react-pdf/renderer's default font (Helvetica) does NOT include
// Vietnamese diacritics. We register Noto Serif (Times New Roman-ish,
// conventional for Vietnamese administrative documents) from Google Fonts.
//
// If your deployment blocks gstatic.com, self-host these TTFs and update
// the `src` URLs below.
// ---------------------------------------------------------------------

Font.register({
  family: 'NotoSerif',
  fonts: [
    {
      src: 'https://raw.githubusercontent.com/google/fonts/main/ofl/notoserif/NotoSerif%5Bwdth,wght%5D.ttf',
      fontWeight: 'normal',
    },
    {
      src: 'https://raw.githubusercontent.com/google/fonts/main/ofl/notoserif/NotoSerif%5Bwdth,wght%5D.ttf',
      fontWeight: 'bold',
    },
    {
      src: 'https://raw.githubusercontent.com/google/fonts/main/ofl/notoserif/NotoSerif-Italic%5Bwdth,wght%5D.ttf',
      fontWeight: 'normal',
      fontStyle: 'italic',
    },
  ],
});

// Prevent aggressive word-break hyphenation for Vietnamese syllables
Font.registerHyphenationCallback((word) => [word]);

// ---------------------------------------------------------------------
// Styles
// ---------------------------------------------------------------------

const styles = StyleSheet.create({
  page: {
    fontFamily: 'NotoSerif',
    fontSize: 11,
    paddingTop: 56,    // 20mm
    paddingBottom: 56,
    paddingLeft: 85,   // 30mm
    paddingRight: 56,
    lineHeight: 1.4,
  },
  header: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 10 },
  headerCol: { width: '48%', textAlign: 'center' },
  headerLine: { fontWeight: 'bold', fontSize: 10 },
  title: {
    textAlign: 'center',
    fontSize: 15,
    fontWeight: 'bold',
    marginTop: 10,
    marginBottom: 4,
  },
  subtitle: {
    textAlign: 'center',
    fontStyle: 'italic',
    fontSize: 11,
    marginBottom: 14,
  },
  sectionTitle: { fontWeight: 'bold', marginTop: 10, marginBottom: 4 },
  body: { textAlign: 'justify' },
  kv: { marginBottom: 2 },
  kvLabel: { fontWeight: 'bold' },
  italic: { fontStyle: 'italic' },

  // tables
  table: { width: '100%', borderStyle: 'solid', borderWidth: 1, borderColor: '#000', marginBottom: 6 },
  tRow: { flexDirection: 'row' },
  tHeader: { backgroundColor: '#f0f0f0' },
  tCell: {
    padding: 3,
    borderRightWidth: 1,
    borderBottomWidth: 1,
    borderColor: '#000',
    fontSize: 9,
  },
  tCellLast: { padding: 3, borderBottomWidth: 1, borderColor: '#000', fontSize: 9 },
  tCellBold: { fontWeight: 'bold', textAlign: 'center' },
  center: { textAlign: 'center' },

  // signatures
  footer: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 18 },
  footerCol: { width: '48%', textAlign: 'center' },
  signSpace: { height: 80 },

  commitment: { textAlign: 'center', fontStyle: 'italic', marginTop: 14, marginBottom: 10 },
  pageFooter: {
    position: 'absolute',
    bottom: 20,
    left: 56,
    right: 56,
    fontSize: 8,
    color: '#666',
    textAlign: 'center',
  },
});

// ---------------------------------------------------------------------
// Sub-components
// ---------------------------------------------------------------------

const box = (checked: boolean) => (checked ? '☒' : '☐');

function FormHeader() {
  return (
    <>
      <View style={styles.header} fixed>
        <View style={styles.headerCol}>
          <Text style={styles.headerLine}>ĐẠI HỌC Y DƯỢC TP.HCM</Text>
          <Text style={styles.headerLine}>HỘI ĐỒNG SÁNG KIẾN</Text>
        </View>
        <View style={styles.headerCol}>
          <Text style={styles.headerLine}>CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM</Text>
          <Text style={styles.headerLine}>Độc lập - Tự do - Hạnh phúc</Text>
        </View>
      </View>
      <Text style={styles.title}>ĐƠN ĐỀ NGHỊ CÔNG NHẬN SÁNG KIẾN</Text>
      <Text style={styles.subtitle}>
        Kính gửi: Hội đồng sáng kiến Đại học Y Dược TP. Hồ Chí Minh
      </Text>
    </>
  );
}

interface Col {
  key: string;
  label: string;
  width: string; // percentage, e.g. '22%'
  align?: 'left' | 'center' | 'right';
}

function DataTable<T extends { id: number }>({
  cols,
  rows,
  render,
  emptyText,
}: {
  cols: Col[];
  rows: T[];
  render: (row: T, idx: number) => (string | number)[];
  emptyText?: string;
}) {
  return (
    <View style={styles.table}>
      {/* header */}
      <View style={[styles.tRow, styles.tHeader]}>
        {cols.map((c, i) => (
          <Text
            key={c.key}
            style={[
              i === cols.length - 1 ? styles.tCellLast : styles.tCell,
              styles.tCellBold,
              { width: c.width },
            ]}
          >
            {c.label}
          </Text>
        ))}
      </View>

      {/* body */}
      {rows.length === 0 && emptyText ? (
        <View style={styles.tRow}>
          <Text style={[styles.tCellLast, styles.italic, styles.center, { width: '100%' }]}>
            {emptyText}
          </Text>
        </View>
      ) : (
        rows.map((row, idx) => {
          const values = render(row, idx);
          return (
            <View key={row.id} style={styles.tRow}>
              {cols.map((c, i) => (
                <Text
                  key={c.key}
                  style={[
                    i === cols.length - 1 ? styles.tCellLast : styles.tCell,
                    { width: c.width, textAlign: c.align ?? 'left' },
                  ]}
                >
                  {String(values[i] ?? '')}
                </Text>
              ))}
            </View>
          );
        })
      )}
    </View>
  );
}

function AuthorsTable({ authors }: { authors: Author[] }) {
  const cols: Col[] = [
    { key: 'n', label: 'STT', width: '6%', align: 'center' },
    { key: 'name', label: 'Họ và tên', width: '22%' },
    { key: 'dob', label: 'Ngày sinh', width: '12%', align: 'center' },
    { key: 'wp', label: 'Nơi công tác', width: '20%' },
    { key: 'ti', label: 'Chức danh', width: '14%' },
    { key: 'q', label: 'Trình độ CM', width: '14%' },
    { key: 'pc', label: '% Đóng góp', width: '12%', align: 'center' },
  ];
  return (
    <DataTable
      cols={cols}
      rows={authors}
      render={(a, i) => [
        i + 1,
        a.name,
        displayDobStoredAsDdMm(a.dob),
        a.workplace,
        a.title,
        a.qualification,
        a.contributionPercent ? `${a.contributionPercent}%` : '',
      ]}
    />
  );
}

function SupportStaffTable({ staff }: { staff: SupportStaff[] }) {
  const cols: Col[] = [
    { key: 'n', label: 'STT', width: '5%', align: 'center' },
    { key: 'name', label: 'Họ và tên', width: '18%' },
    { key: 'dob', label: 'Ngày sinh', width: '11%', align: 'center' },
    { key: 'wp', label: 'Nơi công tác', width: '17%' },
    { key: 'ti', label: 'Chức danh', width: '12%' },
    { key: 'q', label: 'Trình độ CM', width: '12%' },
    { key: 'sc', label: 'Nội dung hỗ trợ', width: '25%' },
  ];
  return (
    <DataTable
      cols={cols}
      rows={staff}
      emptyText="Không có người hỗ trợ"
      render={(s, i) => [
        i + 1,
        s.name,
        displayDobStoredAsDdMm(s.dob),
        s.workplace,
        s.title,
        s.qualification,
        s.supportContent,
      ]}
    />
  );
}

function Classification({ f }: { f: ApplicationFormState }) {
  const attached: string[] = [];
  if (f.technicalEvidenceFile)
    attached.push(`Nhóm 1: ${f.technicalEvidenceFile.name}`);
  if (f.researchEvidenceFile)
    attached.push(`Nhóm 2.1: ${f.researchEvidenceFile.name}`);
  if (f.textbookEvidenceFile)
    attached.push(`Nhóm 2.2: ${f.textbookEvidenceFile.name}`);

  return (
    <View>
      <Text style={styles.sectionTitle}>3. Phân loại sáng kiến:</Text>
      <Text>
        {box(f.initiativeClassification === 'technical')} Nhóm 1 — Giải pháp kỹ thuật,
        quản lý, tác nghiệp, ứng dụng tiến bộ kỹ thuật áp dụng cho Đại học Y Dược TP.HCM
      </Text>
      <Text>
        {box(f.initiativeClassification === 'research')} Nhóm 2.1 — Sáng kiến – cải tiến
        kỹ thuật từ nghiên cứu khoa học (đã đăng tạp chí/hội nghị)
      </Text>
      <Text>
        {box(f.initiativeClassification === 'textbook')} Nhóm 2.2 — Sáng kiến – cải tiến
        kỹ thuật từ sách, giáo trình, tài liệu tham khảo
      </Text>

      {f.initiativeClassification === 'research' && (
        <View style={{ marginTop: 4 }}>
          <Text style={[styles.italic, { fontWeight: 'bold', marginBottom: 2 }]}>
            Loại minh chứng nghiên cứu:
          </Text>
          <Text>{box(f.researchEvidenceKind === 'international')} 2.1.1 — Bài báo tạp chí quốc tế</Text>
          <Text>{box(f.researchEvidenceKind === 'domestic')} 2.1.2 — Bài báo tạp chí trong nước</Text>
          <Text>{box(f.researchEvidenceKind === 'poster')} 2.1.3 — Poster / báo cáo hội nghị có phản biện</Text>
          <Text>
            {box(f.researchEvidenceKind === 'poster-without-review')} 2.1.4 — Poster / báo cáo hội nghị không phản biện
          </Text>
          {f.researchEvidenceKind === 'international' &&
            (() => {
              const bck = ensureBanCamKet(f.banCamKet);
              const legacy = f.internationalJournalDeclaration.trim();
              if (!isBanCamKetComplete(bck) && !legacy) return null;
              return (
                <>
                  <Text style={[styles.italic, { fontWeight: 'bold', marginTop: 4 }]}>
                    Bản cam kết của tác giả (tạp chí quốc tế):
                  </Text>
                  {isBanCamKetComplete(bck) ? (
                    <>
                      <Text style={styles.body}>
                        Ngày ký: {bck.ngay_ky.ngay}/{bck.ngay_ky.thang}/{bck.ngay_ky.nam}
                      </Text>
                      <Text style={styles.body}>Tác giả đăng ký: {bck.tac_gia_dang_ky}</Text>
                      <Text style={styles.body}>CCCD/HC: {bck.cccd}</Text>
                      <Text style={styles.body}>Đơn vị: {bck.don_vi}</Text>
                      <Text style={styles.body}>Tên bài báo: {bck.ten_bai_bao}</Text>
                      <Text style={styles.body}>Năm xét: {bck.nam_xet}</Text>
                      <Text style={styles.body}>
                        Vai trò:{' '}
                        {bck.vai_tro.tac_gia_chinh
                          ? 'Tác giả chính'
                          : bck.vai_tro.dong_tac_gia
                            ? 'Đồng tác giả'
                            : '—'}
                      </Text>
                      <Text style={styles.body}>Người cam kết: {bck.nguoi_cam_ket}</Text>
                    </>
                  ) : (
                    <Text style={styles.body}>{f.internationalJournalDeclaration}</Text>
                  )}
                </>
              );
            })()}
          {f.researchEvidenceKind === 'domestic' &&
            (() => {
              const dj = ensureResearchDomesticHonesty(f.researchDomesticHonesty);
              if (!isResearchDomesticHonestyComplete(dj)) return null;
              return (
                <>
                  <Text style={[styles.italic, { fontWeight: 'bold', marginTop: 4 }]}>
                    Biểu xác nhận bài báo trong nước (2.1.2):
                  </Text>
                  <Text style={styles.body}>
                    Ngày ký: {dj.ngay_ky.ngay}/{dj.ngay_ky.thang}/{dj.ngay_ky.nam}
                  </Text>
                  {dj.tieu_de_phu.trim() ? (
                    <Text style={styles.body}>Tiêu đề phụ: {dj.tieu_de_phu.trim()}</Text>
                  ) : null}
                  <Text style={styles.body}>Tác giả đăng ký: {dj.tac_gia_dang_ky}</Text>
                  <Text style={styles.body}>CCCD/HC: {dj.cccd}</Text>
                  <Text style={styles.body}>Đơn vị: {dj.don_vi}</Text>
                  <Text style={styles.body}>Tên bài báo: {dj.ten_bai_bao}</Text>
                  <Text style={styles.body}>Năm xét công nhận sáng kiến: {dj.nam_xet}</Text>
                  <Text style={styles.body}>Người cam kết: {dj.nguoi_cam_ket}</Text>
                </>
              );
            })()}
        </View>
      )}

      {f.initiativeClassification === 'textbook' && (
        <View style={{ marginTop: 4 }}>
          <Text style={[styles.italic, { fontWeight: 'bold', marginBottom: 2 }]}>
            Loại minh chứng sách/giáo trình:
          </Text>
          <Text>{box(f.textbookEvidenceKind === 'book')} Xuất sắc — Sách, giáo trình</Text>
          <Text>{box(f.textbookEvidenceKind === 'reference')} 2.2.2 — Tài liệu tham khảo</Text>
          {f.textbookEvidenceKind === 'book' &&
            (() => {
              const bck = ensureBanCamKet(f.banCamKet);
              if (!isBanCamKetComplete(bck)) return null;
              return (
                <>
                  <Text style={[styles.italic, { fontWeight: 'bold', marginTop: 4 }]}>
                    Bản cam kết của tác giả (Xuất sắc — Sách, giáo trình):
                  </Text>
                  <Text style={styles.body}>
                    Ngày ký: {bck.ngay_ky.ngay}/{bck.ngay_ky.thang}/{bck.ngay_ky.nam}
                  </Text>
                  <Text style={styles.body}>Tác giả đăng ký: {bck.tac_gia_dang_ky}</Text>
                  <Text style={styles.body}>CCCD/HC: {bck.cccd}</Text>
                  <Text style={styles.body}>Đơn vị: {bck.don_vi}</Text>
                  <Text style={styles.body}>Tên bài báo/sách (biểu mẫu): {bck.ten_bai_bao}</Text>
                  <Text style={styles.body}>Năm xét: {bck.nam_xet}</Text>
                  <Text style={styles.body}>Người cam kết: {bck.nguoi_cam_ket}</Text>
                </>
              );
            })()}
          {f.textbookEvidenceKind === 'reference' &&
            (() => {
              const rm = ensureReferenceMaterialHonesty(f.referenceMaterialHonesty);
              if (!isReferenceMaterialHonestyComplete(rm)) return null;
              return (
                <>
                  <Text style={[styles.italic, { fontWeight: 'bold', marginTop: 4 }]}>
                    Biểu xác nhận tài liệu tham khảo (2.2.2):
                  </Text>
                  <Text style={styles.body}>
                    Ngày ký: {rm.ngay_ky.ngay}/{rm.ngay_ky.thang}/{rm.ngay_ky.nam}
                  </Text>
                  <Text style={styles.body}>Tác giả đăng ký: {rm.tac_gia_dang_ky}</Text>
                  <Text style={styles.body}>CCCD/HC: {rm.cccd}</Text>
                  <Text style={styles.body}>Đơn vị: {rm.don_vi}</Text>
                  <Text style={styles.body}>Tên tài liệu: {rm.ten_tai_lieu}</Text>
                  <Text style={styles.body}>Năm xét: {rm.nam_xet}</Text>
                  <Text style={styles.body}>Người cam kết: {rm.nguoi_cam_ket}</Text>
                </>
              );
            })()}
        </View>
      )}

      {attached.length > 0 && (
        <View style={{ marginTop: 4 }}>
          <Text style={[styles.italic, { fontWeight: 'bold' }]}>
            File minh chứng đính kèm:
          </Text>
          {attached.map((line) => (
            <Text key={line}>• {line}</Text>
          ))}
        </View>
      )}
    </View>
  );
}

function KV({ label, value }: { label: string; value: string }) {
  return (
    <Text style={styles.kv}>
      <Text style={styles.kvLabel}>{label}: </Text>
      {value || '…'}
    </Text>
  );
}

function SignatureBlock({ f }: { f: ApplicationFormState }) {
  const dateLine =
    f.submissionDay || f.submissionMonth || f.submissionYear
      ? `TP. Hồ Chí Minh, ngày ${f.submissionDay || '…'} tháng ${f.submissionMonth || '…'} năm ${f.submissionYear || '…'}`
      : 'TP. Hồ Chí Minh, ngày … tháng … năm ……';

  return (
    <View style={styles.footer}>
      <View style={styles.footerCol}>
        <Text style={{ fontWeight: 'bold' }}>XÁC NHẬN CỦA LÃNH ĐẠO ĐƠN VỊ</Text>
        <Text style={styles.italic}>(Ký và đóng dấu)</Text>
        <View style={styles.signSpace} />
      </View>
      <View style={styles.footerCol}>
        <Text style={styles.italic}>{dateLine}</Text>
        <Text style={{ fontWeight: 'bold', marginTop: 2 }}>
          TÁC GIẢ CHÍNH / ĐẠI DIỆN NHÓM TÁC GIẢ SÁNG KIẾN
        </Text>
        <Text style={styles.italic}>(chữ ký và ghi rõ họ tên)</Text>
        <View style={styles.signSpace} />
      </View>
    </View>
  );
}

// ---------------------------------------------------------------------
// Main document
// ---------------------------------------------------------------------

function ApplicationPdfPage({ data, draftId }: { data: ApplicationFormState; draftId?: string }) {
  return (
    <Page size="A4" style={styles.page}>
      <FormHeader />

      <Text style={styles.sectionTitle}>1. Tên tôi (chúng tôi) là:</Text>
      <AuthorsTable authors={data.authors} />

      <Text style={styles.sectionTitle}>2. Thông tin sáng kiến</Text>
      <KV label="Tên đơn vị" value={data.unitName} />
      <KV label="Tên sáng kiến đề nghị công nhận" value={data.initiativeName} />
      <KV label="Chủ đầu tư tạo ra sáng kiến (nếu khác tác giả)" value={data.investorName} />
      <KV label="Lĩnh vực áp dụng" value={data.applicationField} />
      <KV label="Ngày sáng kiến được áp dụng lần đầu" value={data.firstApplyDate} />

      <Classification f={data} />

      <Text style={styles.sectionTitle}>4. Nội dung của sáng kiến:</Text>
      <Text style={styles.italic}>
        (Mô tả ngắn gọn, đầy đủ các bước thực hiện, kết quả, hiệu quả thử nghiệm)
      </Text>
      <Text style={styles.body}>{data.contentSummary || '…'}</Text>

      <Text style={styles.sectionTitle}>Thông tin cần bảo mật (nếu có):</Text>
      <Text style={styles.body}>{data.confidentialInfo || '…'}</Text>

      <Text style={styles.sectionTitle}>Các điều kiện cần thiết để áp dụng:</Text>
      <Text style={styles.body}>{data.conditions || '…'}</Text>

      <Text style={styles.sectionTitle}>5. Đánh giá lợi ích (theo ý kiến tác giả):</Text>
      <Text style={styles.body}>{data.authorEvaluation || '…'}</Text>

      <Text style={styles.sectionTitle}>6. Đánh giá lợi ích (theo đơn vị áp dụng thử):</Text>
      <Text style={styles.body}>{data.trialEvaluation || '…'}</Text>

      <Text style={styles.sectionTitle}>7. Danh sách người tham gia áp dụng thử / lần đầu:</Text>
      <SupportStaffTable staff={data.supportStaff} />

      <Text style={styles.commitment}>
        Tôi xin cam đoan mọi thông tin nêu trong đơn là trung thực, đúng sự thật và hoàn toàn chịu
        trách nhiệm trước pháp luật.
      </Text>

      <SignatureBlock f={data} />

      <Text
        style={styles.pageFooter}
        render={({ pageNumber, totalPages }) =>
          draftId
            ? `Trang ${pageNumber} / ${totalPages} — ${draftId}`
            : `Trang ${pageNumber} / ${totalPages}`
        }
        fixed
      />
    </Page>
  );
}

function ReportPdfPage({ report, draftId }: { report: InitiativeFormState; draftId: string }) {
  return (
    <Page size="A4" style={styles.page}>
      <Text style={styles.title}>BÁO CÁO MÔ TẢ SÁNG KIẾN</Text>
      <Text style={styles.subtitle}>Kính gửi: Hội đồng sáng kiến Đại học Y Dược TP. Hồ Chí Minh</Text>

      <KV label="Tên sáng kiến" value={report.initiativeName} />
      <KV label="Tác giả chính / Đại diện nhóm tác giả sáng kiến" value={report.representativeAuthor} />
      <KV label="Điện thoại" value={report.representativePhone} />
      <KV label="Email" value={report.representativeEmail} />
      <KV label="Lĩnh vực áp dụng" value={report.applicationField} />

      <Text style={styles.sectionTitle}>Mở đầu</Text>
      <Text style={styles.body}>{report.introduction || '…'}</Text>

      <Text style={styles.sectionTitle}>Hiện trạng</Text>
      <Text style={styles.body}>{report.currentStatus || '…'}</Text>

      <Text style={styles.sectionTitle}>Mục đích / nội dung giải pháp</Text>
      <Text style={styles.body}>{report.purpose || '…'}</Text>
      <Text style={styles.body}>{report.solutionContent || '…'}</Text>

      <Text style={styles.sectionTitle}>Các bước thực hiện</Text>
      <Text style={styles.body}>{report.implementationSteps || '…'}</Text>

      <KV label="Đơn vị áp dụng lần đầu" value={report.firstAppliedUnit} />
      <KV label="Kết quả thu được" value={report.achievedResult} />
      <KV label="Điều kiện áp dụng" value={report.conditions} />

      <Text style={styles.sectionTitle}>Đơn vị / cá nhân áp dụng thử</Text>
      {report.trialUnits.length === 0 ? (
        <Text style={styles.body}>—</Text>
      ) : (
        report.trialUnits.map((u, i) => (
          <KV
            key={u.id}
            label={`Đơn vị ${i + 1}`}
            value={`${u.name} — ${u.address} (${u.field})`}
          />
        ))
      )}

      <Text style={styles.sectionTitle}>Tính mới</Text>
      <Text style={styles.body}>{report.novelty || '…'}</Text>

      <Text style={styles.sectionTitle}>Hiệu quả</Text>
      <KV label="Kinh tế" value={report.effectiveness.economic} />
      <KV label="Xã hội / nhận thức" value={report.effectiveness.social} />
      <KV label="Giảng dạy / công việc" value={report.effectiveness.teaching} />
      <KV label="Năng suất" value={report.effectiveness.productivity} />
      <KV label="Chất lượng" value={report.effectiveness.quality} />
      <KV label="Môi trường" value={report.effectiveness.environment} />
      <KV label="An toàn" value={report.effectiveness.safety} />

      <Text style={styles.sectionTitle}>Thông tin bảo mật (nếu có)</Text>
      <Text style={styles.body}>{report.confidentialInfo || '…'}</Text>

      <KV label="Ngày nộp (báo cáo)" value={formatVnDateFieldForDisplay(report.submissionDate)} />
      <KV label="Họ tên (chữ ký và ghi rõ họ tên)" value={report.authorName} />

      <Text
        style={styles.pageFooter}
        render={({ pageNumber, totalPages }) => `Trang ${pageNumber} / ${totalPages} — ${draftId}`}
        fixed
      />
    </Page>
  );
}

function ApplicationPdfDocument({ data }: { data: ApplicationFormState }) {
  return (
    <Document title="Đơn đề nghị công nhận sáng kiến" author="Initiative Application Form">
      <ApplicationPdfPage data={data} />
    </Document>
  );
}

function FullDraftPdfDocument({
  draft,
  application,
}: {
  draft: InitiativeDraft;
  application: ApplicationFormState;
}) {
  return (
    <Document title={`Hồ sơ ${draft.draftId}`} author="Initiative draft">
      <ApplicationPdfPage data={application} draftId={draft.draftId} />
      <ReportPdfPage report={draft.report} draftId={draft.draftId} />
    </Document>
  );
}

// ---------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------

const DEFAULT_FILENAME = 'Don-de-nghi-cong-nhan-sang-kien.pdf';

function triggerDownload(blob: Blob, fileName: string) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = fileName;
  a.click();
  URL.revokeObjectURL(url);
}

function safeFileName(base: string) {
  const cleaned = base.replace(/[^a-zA-Z0-9_\-\u00C0-\u024F\s]+/g, '-').trim();
  return cleaned || 'ho-so-sang-kien';
}

async function hydrateApplicationFromDraft(
  draft: InitiativeDraft,
  initiativeCaseId?: string | null,
): Promise<ApplicationFormState> {
  const a = draft.application;
  const cid = initiativeCaseId?.trim() || null;
  const [t, r, tech] = await Promise.all([
    getFile(a.textbookEvidenceFile, { caseId: cid, serverKind: 'textbook' }),
    getFile(a.researchEvidenceFile, { caseId: cid, serverKind: 'research' }),
    getFile(a.technicalEvidenceFile, { caseId: cid, serverKind: 'technical' }),
  ]);
  return {
    ...a,
    textbookEvidenceFile: t,
    researchEvidenceFile: r,
    technicalEvidenceFile: tech,
  };
}

/**
 * Đơn đề nghị + báo cáo mô tả trong một file PDF (đọc minh chứng từ IndexedDB hoặc MinIO khi có `initiativeCaseId`).
 */
export async function exportDraftPdf(
  draft: InitiativeDraft,
  initiativeCaseId?: string | null,
): Promise<void> {
  const application = await hydrateApplicationFromDraft(draft, initiativeCaseId);
  const blob = await pdf(<FullDraftPdfDocument draft={draft} application={application} />).toBlob();
  const name = `${safeFileName(
    draft.report.initiativeName || draft.application.initiativeName || draft.draftId,
  )}.pdf`;
  triggerDownload(blob, name);
}

/**
 * Chỉ đơn đề nghị (một file, một hoặc nhiều trang tùy độ dài nội dung).
 */
export async function exportApplicationFormPdf(
  data: ApplicationFormState,
  fileName: string = DEFAULT_FILENAME,
): Promise<void> {
  const blob = await pdf(<ApplicationPdfDocument data={data} />).toBlob();
  triggerDownload(blob, fileName);
}

/** Blob đơn đề nghị (upload / iframe preview). */
export async function renderApplicationPdfBlob(data: ApplicationFormState): Promise<Blob> {
  return pdf(<ApplicationPdfDocument data={data} />).toBlob();
}

/** Blob đầy đủ đơn + báo cáo. */
export async function renderFullDraftPdfBlob(
  draft: InitiativeDraft,
  initiativeCaseId?: string | null,
): Promise<Blob> {
  const application = await hydrateApplicationFromDraft(draft, initiativeCaseId);
  return withPromiseTimeout(
    pdf(<FullDraftPdfDocument draft={draft} application={application} />).toBlob(),
    PDF_RENDER_DEADLINE_MS,
    `Tạo file PDF quá lâu (qua ${Math.round(PDF_RENDER_DEADLINE_MS / 1000)} giây). Kiểm tra kết nối mạng hoặc thử đóng tab khác rồi gửi lại.`,
  );
}

export { ApplicationPdfDocument, FullDraftPdfDocument, ApplicationPdfPage, ReportPdfPage };
