import jsPDF from 'jspdf';
import autoTable from 'jspdf-autotable';
import { format } from 'date-fns';

function generateHash(election, tallies) {
  const data = `${election.id}-${JSON.stringify(tallies)}-${Date.now()}`;
  let hash = 0;
  for (let i = 0; i < data.length; i++) {
    const char = data.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash |= 0;
  }
  return Math.abs(hash).toString(16).toUpperCase().padStart(8, '0');
}

export function generateCertificationPDF({ election, positions, candidates, voters, tallies }) {
  const doc = new jsPDF();
  const pageW = doc.internal.pageSize.getWidth();
  const pageH = doc.internal.pageSize.getHeight();
  let y = 20;

  // Navy header bar
  doc.setFillColor(30, 58, 95);
  doc.rect(0, 0, pageW, 35, 'F');

  doc.setTextColor(255, 255, 255);
  doc.setFontSize(18);
  doc.setFont('helvetica', 'bold');
  doc.text('CERTIFICATE OF ELECTION', pageW / 2, 18, { align: 'center' });
  doc.setFontSize(9);
  doc.setFont('helvetica', 'normal');
  doc.text('Official Certified Results', pageW / 2, 28, { align: 'center' });

  doc.setTextColor(0, 0, 0);
  y = 45;

  // Association name
  doc.setFontSize(14);
  doc.setFont('helvetica', 'bold');
  doc.text(election.association?.name || 'Association', pageW / 2, y, { align: 'center' });
  y += 8;

  doc.setFontSize(12);
  doc.setFont('helvetica', 'normal');
  doc.text(election.title, pageW / 2, y, { align: 'center' });
  y += 12;

  // Election details
  doc.setFontSize(9);
  const votedOnlineCount = voters.filter(v => v.has_voted).length;
  const totalParticipation = votedOnlineCount + (election.proxies_count || 0) + (election.in_person_count || 0);
  const totalTallyVotes = Object.values(tallies).reduce((a, b) => a + b, 0);

  const details = [
    ['Election Type', election.election_type?.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()) || 'Board of Directors'],
    ['Voting Period', `${election.voting_start ? format(new Date(election.voting_start), 'MMM d, yyyy') : 'N/A'} — ${election.voting_end ? format(new Date(election.voting_end), 'MMM d, yyyy') : 'N/A'}`],
    ['Date Certified', format(new Date(), 'MMMM d, yyyy')],
    ['Eligible Voters', String(voters.length)],
    ['Online Votes', String(votedOnlineCount)],
    ['Proxies', String(election.proxies_count || 0)],
    ['In-Person Ballots', String(totalTallyVotes)],
    ['Total Participation', String(totalParticipation + totalTallyVotes)],
    ['Quorum Required', election.quorum_required > 0 ? String(election.quorum_required) : 'N/A'],
    ['Quorum Met', election.quorum_required > 0 ? ((totalParticipation + totalTallyVotes) >= election.quorum_required ? 'YES' : 'NO') : 'N/A'],
  ];

  autoTable(doc, {
    startY: y,
    body: details,
    theme: 'plain',
    styles: { fontSize: 9, cellPadding: 2 },
    columnStyles: {
      0: { fontStyle: 'bold', cellWidth: 50 },
      1: { cellWidth: 'auto' },
    },
    margin: { left: 30, right: 30 },
  });
  y = doc.lastAutoTable.finalY + 10;

  // Separator
  doc.setDrawColor(30, 58, 95);
  doc.setLineWidth(0.8);
  doc.line(30, y, pageW - 30, y);
  y += 10;

  // Results heading
  doc.setFontSize(13);
  doc.setFont('helvetica', 'bold');
  doc.text('CERTIFIED RESULTS', pageW / 2, y, { align: 'center' });
  y += 10;

  // Results per position
  positions.forEach(pos => {
    const posCandidates = candidates.filter(c => c.position_id === pos.id);
    const posTotal = posCandidates.reduce((sum, c) => sum + (tallies[c.id] || 0), 0);

    // Sort candidates by votes descending
    const sorted = [...posCandidates].sort((a, b) => (tallies[b.id] || 0) - (tallies[a.id] || 0));
    const winners = sorted.slice(0, pos.seats_available);

    const body = sorted.map((c, idx) => {
      const count = tallies[c.id] || 0;
      const pct = posTotal > 0 ? Math.round((count / posTotal) * 100) : 0;
      const isWinner = winners.some(w => w.id === c.id) && count > 0;
      return [
        isWinner ? `★ ${c.candidate_name}` : `   ${c.candidate_name}`,
        String(count),
        `${pct}%`,
        isWinner ? 'ELECTED' : '',
      ];
    });

    if (y > 230) { doc.addPage(); y = 20; }

    autoTable(doc, {
      startY: y,
      head: [[`${pos.title} (${pos.seats_available} seat${pos.seats_available > 1 ? 's' : ''})`, 'Votes', '%', 'Result']],
      body,
      theme: 'grid',
      headStyles: { fillColor: [30, 58, 95], fontSize: 9, fontStyle: 'bold' },
      bodyStyles: { fontSize: 9 },
      columnStyles: {
        3: { fontStyle: 'bold', textColor: [30, 58, 95] },
      },
      margin: { left: 30, right: 30 },
      didParseCell: function(data) {
        if (data.section === 'body' && data.row.raw[3] === 'ELECTED') {
          data.cell.styles.fillColor = [235, 245, 255];
        }
      },
    });
    y = doc.lastAutoTable.finalY + 8;
  });

  // Compliance section
  if (y > 220) { doc.addPage(); y = 20; }
  y += 5;
  doc.setDrawColor(30, 58, 95);
  doc.setLineWidth(0.5);
  doc.line(30, y, pageW - 30, y);
  y += 8;

  doc.setFontSize(10);
  doc.setFont('helvetica', 'bold');
  doc.text('CERTIFICATION STATEMENT', 30, y);
  y += 7;

  doc.setFontSize(8);
  doc.setFont('helvetica', 'normal');
  const certLines = [
    'I hereby certify that the above election results are true and accurate to the best of my knowledge.',
    'All votes were counted in accordance with the governing documents of the association and',
    'applicable state statutes (FL §718.112 / §720.306). Ballot secrecy was maintained throughout',
    'the election process. An independent audit trail exists recording participation without',
    'revealing individual vote choices.',
    '',
    `Verification Hash: ${generateHash(election, tallies)}`,
  ];
  certLines.forEach(line => { doc.text(line, 30, y); y += 4.5; });

  // Signature lines
  y += 15;
  if (y > 260) { doc.addPage(); y = 30; }

  doc.setLineWidth(0.3);
  doc.setDrawColor(0, 0, 0);

  // Left signature
  doc.line(30, y, 95, y);
  y += 5;
  doc.setFontSize(8);
  doc.text('Election Inspector / Secretary', 30, y);

  // Right signature
  doc.line(pageW / 2 + 15, y - 5, pageW - 30, y - 5);
  doc.text('Date', pageW / 2 + 15, y);

  y += 12;
  doc.line(30, y, 95, y);
  y += 5;
  doc.text('Association President / Chair', 30, y);

  doc.line(pageW / 2 + 15, y - 5, pageW - 30, y - 5);
  doc.text('Date', pageW / 2 + 15, y);

  // Footer
  const totalPages = doc.internal.getNumberOfPages();
  for (let i = 1; i <= totalPages; i++) {
    doc.setPage(i);
    doc.setFontSize(7);
    doc.setTextColor(150, 150, 150);
    doc.text(`Page ${i} of ${totalPages}`, pageW / 2, pageH - 10, { align: 'center' });
    doc.text(`Generated: ${format(new Date(), 'MMM d, yyyy h:mm a')}`, pageW - 15, pageH - 10, { align: 'right' });
    doc.setTextColor(0, 0, 0);
  }

  const fileName = `Election_Certification_${election.title.replace(/\s+/g, '_')}_${format(new Date(), 'yyyy-MM-dd')}.pdf`;
  doc.save(fileName);
  return fileName;
}