// contracts-billing.jsx — Графік фінансування договорів: життєвий цикл етапу,
// дії на рядку (рахунок / акт / оплата), реєстр додаткових угод.
//
// Правило каналу оплати (за реквізитами замовника):
//   • казна (держ. замовник)  → ЛИШЕ акт (рахунок не виставляємо)
//   • банк (госпрозрахунок)    → рахунок + акт; аванс на банк — лише рахунок
//
// Етап графіку (schedule item) збагачено полями:
//   billing: "advance" | "work"   — аванс (без акта) / за виконані роботи (з актом)
//   edessb:  bool                 — етап пов'язаний з ЄДЕССБ / експертизою
//   dueDate (план) / factDate     — планова vs фактична дата готовності етапу
//   invoiceNo / invoiceDate       — № і дата виставленого рахунку
//   actNo / actDate               — № і дата підписаного акта
//   paidDate                      — фактична дата оплати
//   ready: bool                   — готовність етапу (роботи виконані на об'єкті)
(function () {

  const TODAY = window.TODAY_ISO || "2026-05-26";

  // ── Канал оплати ───────────────────────────────────────────
  // Держ. замовник (type:"state") платить через Держказну → лише акт.
  window.billingChannel = function (contract) {
    const client = window.getClient(contract.client);
    return client && client.type === "state" ? "treasury" : "bank";
  };
  window.BILLING_CHANNEL = {
    treasury: { label: "Казна — лише акт", short: "Казна", icon: "landmark", tone: "neutral",
      note: "Держ. замовник: оплата через Держказначейство за підписаним актом. Рахунок не виставляється." },
    bank:     { label: "Банк — рахунок + акт", short: "Банк", icon: "banknote", tone: "live",
      note: "Госпрозрахунковий замовник: спершу рахунок, акт за виконаними роботами, далі оплата." },
  };

  // ── Роль сторін у договорі (відома на етапі укладення) ──────
  // Наш бік: Виконавець (договір про надання послуг) або Підрядник (договір підряду).
  // Контрагент: Замовник або Генпідрядник (коли ми субпідрядник).
  // Предмет акта (надані послуги / виконані роботи) — теж залежить від договору.
  window.ACT_OUR_ROLES = {
    executor:   { label: "ВИКОНАВЕЦЬ", labelGen: "Виконавця",  short: "Виконавець" },
    contractor: { label: "ПІДРЯДНИК",  labelGen: "Підрядника", short: "Підрядник" },
  };
  window.ACT_COUNTER_ROLES = {
    customer:      { label: "ЗАМОВНИК",     labelGen: "Замовника",     short: "Замовник" },
    genContractor: { label: "ГЕНПІДРЯДНИК", labelGen: "Генпідрядника", short: "Генпідрядник" },
  };
  window.ACT_SUBJECTS = {
    services: { titleSuffix: "наданих послуг",  verb: "надав",   verbPl: "надано",   noun: "послуги", genPl: "послуг", unit: "послуга", noteDone: "Послуги надані в повному обсязі" },
    works:    { titleSuffix: "виконаних робіт", verb: "виконав", verbPl: "виконано", noun: "роботи",  genPl: "робіт",  unit: "робота",  noteDone: "Роботи виконані в повному обсязі" },
  };

  // Нормалізовані ролі договору (з дефолтами)
  window.contractParties = function (contract) {
    const p = (contract && contract.parties) || {};
    const ourRole = p.ourRole === "contractor" ? "contractor" : "executor";
    // Виконавець завжди працює із Замовником; Генпідрядник можливий лише як субпідрядник
    const counterRole = ourRole === "executor"
      ? "customer"
      : (p.counterRole === "genContractor" ? "genContractor" : "customer");
    const subject = p.subject === "works" || p.subject === "services"
      ? p.subject
      : (ourRole === "contractor" ? "works" : "services");
    return { ourRole, counterRole, subject };
  };

  // Повний конфіг формулювань для акта
  window.actRoleConfig = function (contract) {
    const { ourRole, counterRole, subject } = window.contractParties(contract);
    return {
      ourRole, counterRole, subject,
      our: window.ACT_OUR_ROLES[ourRole],
      counter: window.ACT_COUNTER_ROLES[counterRole],
      subj: window.ACT_SUBJECTS[subject],
    };
  };

  // ── Які документи потрібні для етапу ───────────────────────
  window.stageDocs = function (contract, stage) {
    const channel = window.billingChannel(contract);
    const isAdvance = stage.billing === "advance";
    return {
      channel,
      needsInvoice: channel === "bank",                       // казна — без рахунку
      needsAct: channel === "treasury" || !isAdvance,         // казна завжди; банк — лише «за роботи»
    };
  };

  // ── Статус етапу (обчислюється з наявних документів) ───────
  window.STAGE_STATUS = {
    planned:  { label: "Заплановано",         tone: "neutral", icon: "circle" },
    invoiced: { label: "Рахунок виставлено",  tone: "blue",    icon: "file" },
    acted:    { label: "Акт підписано",       tone: "amber",   icon: "checkCircle" },
    paid:     { label: "Оплачено",            tone: "live",    icon: "check" },
    overdue:  { label: "Прострочено",         tone: "warn",    icon: "alert" },
  };
  window.stageStatus = function (contract, stage) {
    const d = window.stageDocs(contract, stage);
    if (stage.paidDate) return "paid";
    let s = "planned";
    if (d.needsInvoice && stage.invoiceNo) s = "invoiced";
    if (d.needsAct && stage.actDate) s = "acted";
    // прострочення — лише поки не оплачено й термін минув
    if (s === "planned" && stage.dueDate && stage.dueDate < TODAY) return "overdue";
    return s;
  };

  // ── Доступні дії на рядку ──────────────────────────────────
  // Повертає масив { key, label, icon, kind } у логічному порядку.
  window.stageActions = function (contract, stage) {
    const d = window.stageDocs(contract, stage);
    const acts = [];
    if (stage.paidDate) return acts; // закрито
    if (d.needsInvoice && !stage.invoiceNo)
      acts.push({ key: "invoice", label: "Виставити рахунок", icon: "file", kind: "default" });
    if (d.needsAct && !stage.actDate)
      acts.push({ key: "act", label: "Сформувати акт", icon: "clipboard", kind: "default" });
    // оплату можна позначити, коли всі потрібні документи готові
    const invoiceReady = !d.needsInvoice || stage.invoiceNo;
    const actReady = !d.needsAct || stage.actDate;
    if (invoiceReady && actReady)
      acts.push({ key: "pay", label: "Позначити оплаченим", icon: "check", kind: "primary" });
    return acts;
  };

  // ── Зведення по договору (для шапки) ───────────────────────
  window.contractBillingSummary = function (contract) {
    const sched = contract.schedule || [];
    let paid = 0, invoiced = 0, acted = 0, overdue = 0, planned = 0;
    sched.forEach(s => {
      const st = window.stageStatus(contract, s);
      if (st === "paid") paid += s.amount;
      else if (st === "overdue") overdue += s.amount;
      else if (st === "acted") acted += s.amount;
      else if (st === "invoiced") invoiced += s.amount;
      else planned += s.amount;
    });
    const billed = invoiced + acted; // у роботі, ще не оплачено
    return { paid, billed, overdue, planned, acted, invoiced };
  };

  // ═══════════════ ЗБАГАЧЕННЯ НАЯВНИХ ДАНИХ ═══════════════
  // Інференс типу етапу за назвою (аванс / роботи) + ЄДЕССБ-маркер.
  function inferBilling(stageName) {
    return /аванс/i.test(stageName) ? "advance" : "work";
  }
  function inferEdessb(stageName) {
    return /єдессб|експертиз/i.test(stageName);
  }
  // Підтягнути № і дату рахунку з вже існуючого реєстру INVOICES.
  function invoiceMeta(invId) {
    const inv = (window.DATA.INVOICES || []).find(i => i.id === invId);
    return inv ? { invoiceNo: inv.number, invoiceDate: inv.issueDate } : {};
  }

  function enrichSchedule() {
    (window.DATA.CONTRACTS || []).forEach(c => {
      const channel = window.billingChannel(c);
      (c.schedule || []).forEach((s, idx) => {
        if (s.billing == null) s.billing = inferBilling(s.stage);
        if (s.edessb == null) s.edessb = inferEdessb(s.stage);
        // рахунок: з реєстру INVOICES (лише для банківського каналу)
        if (channel === "bank" && s.invoice && s.invoiceNo == null) {
          Object.assign(s, invoiceMeta(s.invoice));
        }
        // акт: для оплачених «робочих» етапів вважаємо акт підписаним
        const needsAct = channel === "treasury" || s.billing !== "advance";
        if (needsAct && s.paidDate && s.actNo == null) {
          const obj = window.getObject(c.obj);
          const codeNum = obj && obj.code ? (obj.code.match(/(\d+)\s*$/) || [])[1] : (c.number || "").split("/")[0];
          s.actNo = `${codeNum}-АКТ-${String(idx + 1).padStart(2, "0")}`;
          // акт підписують орієнтовно за 3 дні до оплати
          const d = new Date(s.paidDate); d.setDate(d.getDate() - 3);
          s.actDate = d.toISOString().slice(0, 10);
        }
        // фактична дата готовності етапу
        if (s.factDate == null) {
          if (s.paidDate) s.factDate = s.actDate || s.dueDate;
          else s.factDate = null;
        }
        if (s.ready == null) s.ready = !!s.paidDate;
      });
    });
  }

  // ── Реєстр додаткових угод (приклади на наявних договорах) ──
  function installAmendments() {
    const map = {
      "k-47": [
        { no: "1", date: "2025-12-20", reason: "Зміна графіку фінансування",
          changes: [
            "Додано етап «Реєстрація в ЄДЕССБ» (10%, 840 000 ₴)",
            "Термін «Здача робочого проєкту»: 30.04 → 12.06.2026",
          ] },
      ],
      "k-32": [
        { no: "1", date: "2026-01-15", reason: "Перенесення термінів за результатами тендеру",
          changes: [
            "Аванс після тендеру: 25% → 30% (930 000 ₴)",
            "Термін «Експертиза кошторису»: 31.03 → 30.04.2026",
          ] },
        { no: "2", date: "2026-04-05", reason: "Збільшення обсягу — додатковий корпус",
          changes: [
            "Загальна сума договору: 2 850 000 → 3 100 000 ₴",
            "Перерозподіл часток етапів робочого проєкту",
          ] },
      ],
      "k-89": [
        { no: "1", date: "2025-07-01", reason: "Продовження на авторський нагляд",
          changes: [
            "Додано етапи авторського нагляду (2×5%, разом 80 000 ₴)",
            "Статус договору: активний → авт. нагляд",
          ] },
      ],
    };
    (window.DATA.CONTRACTS || []).forEach(c => {
      if (c.amendments == null) c.amendments = map[c.id] || [];
      // Ролі сторін: усі наявні договори — ми Виконавець (за домовленістю)
      if (c.parties == null) c.parties = { ourRole: "executor", counterRole: "customer", subject: "services" };
    });
  }

  enrichSchedule();
  installAmendments();
  window.enrichSchedule = enrichSchedule;

  // ═══════════════ КОМПОНЕНТ ГРАФІКА ═══════════════
  const { useState } = React;
  const Ico = window.Ico;
  const money = (n) => (window.formatMoney ? window.formatMoney(n) : n);
  const fmtDate = (iso) => (window.formatDate ? window.formatDate(iso) : iso);
  const shortDate = (iso) => {
    if (!iso) return "—";
    const d = new Date(iso);
    if (isNaN(d)) return iso;
    return `${String(d.getDate()).padStart(2, "0")}.${String(d.getMonth() + 1).padStart(2, "0")}.${String(d.getFullYear()).slice(2)}`;
  };

  // Один документ у міні-треку (Рахунок / Акт / Оплата)
  function DocChip({ label, icon, no, date, done, dim, muted }) {
    return (
      <div className={`bs-doc ${done ? "is-done" : ""} ${muted ? "is-muted" : ""}`} title={no ? `${label} № ${no} від ${fmtDate(date)}` : (muted ? `${label} — не потрібен` : `${label} — ще не оформлено`)}>
        <span className="bs-doc-ic"><Ico name={done ? "check" : icon} size={12} /></span>
        <span className="bs-doc-body">
          <span className="bs-doc-label">{label}</span>
          <span className="bs-doc-val">{muted ? "не потрібен" : (no ? `№ ${no} · ${shortDate(date)}` : "—")}</span>
        </span>
      </div>
    );
  }

  function StageRow({ contract, stage, idx, onAction, role }) {
    const d = window.stageDocs(contract, stage);
    const st = window.stageStatus(contract, stage);
    const stInfo = window.STAGE_STATUS[st];
    const actions = window.stageActions(contract, stage);
    const isLate = st === "overdue";
    const factDiffers = stage.factDate && stage.dueDate && stage.factDate !== stage.dueDate;

    return (
      <div className={`bs-stage ${st === "paid" ? "is-paid" : ""} ${isLate ? "is-late" : ""}`}>
        <div className="bs-num td-mono">{idx + 1}</div>

        <div className="bs-main">
          <div className="bs-stage-name">
            {stage.stage}
            {stage.edessb && <span className="bs-chip bs-chip-edessb" title="Етап пов'язаний з ЄДЕССБ / експертизою">ЄДЕССБ</span>}
          </div>
          <div className="bs-stage-sub">
            <span className={`bs-type ${stage.billing === "advance" ? "is-advance" : "is-work"}`}>
              {stage.billing === "advance" ? "Аванс" : "За виконані роботи"}
            </span>
            <span className="bs-dot"></span>
            <span className="bs-pct td-mono">{stage.pct}%</span>
            <span className="bs-dot"></span>
            <span className={`bs-due ${isLate ? "is-late" : ""}`}>
              план {shortDate(stage.dueDate)}
              {factDiffers && <span className="bs-fact"> · факт {shortDate(stage.factDate)}</span>}
              {isLate && <span className="bs-late-days"> · +{window.daysBetween(stage.dueDate, TODAY)} дн.</span>}
            </span>
          </div>
        </div>

        <div className="bs-amount">
          <div className="bs-amount-val td-mono">{money(stage.amount)} ₴</div>
          <div className={`status-tag tone-${stInfo.tone} bs-status`}>{stInfo.label}</div>
        </div>

        <div className="bs-track">
          {d.needsInvoice
            ? <DocChip label="Рахунок" icon="file" no={stage.invoiceNo} date={stage.invoiceDate} done={!!stage.invoiceNo} />
            : <DocChip label="Рахунок" icon="file" muted={true} />}
          {d.needsAct
            ? <DocChip label="Акт" icon="clipboard" no={stage.actNo} date={stage.actDate} done={!!stage.actDate} />
            : <DocChip label="Акт" icon="clipboard" muted={true} />}
          <DocChip label="Оплата" icon="banknote" no={stage.paidDate ? "✓" : null} date={stage.paidDate}
            done={!!stage.paidDate} />
        </div>

        <div className="bs-actions">
          {actions.length === 0 && stage.paidDate && <span className="bs-closed"><Ico name="check" size={14} /> закрито</span>}
          {actions.map(a => (
            <button key={a.key} className={`btn btn-sm ${a.kind === "primary" ? "btn-primary" : ""}`}
              onClick={() => onAction(idx, a.key)}>
              <Ico name={a.icon} size={14} /> {a.label}
            </button>
          ))}
        </div>
      </div>
    );
  }

  // Реєстр додаткових угод
  function AmendmentsBlock({ contract }) {
    const ams = contract.amendments || [];
    const [open, setOpen] = useState(false);
    if (!ams.length) return null;
    return (
      <div className="bs-amend">
        <button className="bs-amend-head" onClick={() => setOpen(o => !o)}>
          <Ico name="file" size={14} />
          <span>Додаткові угоди</span>
          <span className="bs-amend-count">{ams.length}</span>
          <span className={`bs-amend-chev ${open ? "is-open" : ""}`}>
            <svg width="13" height="13" viewBox="0 0 14 14" fill="none"><path d="M3 5L7 9L11 5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>
          </span>
        </button>
        {open && (
          <div className="bs-amend-list">
            {ams.map((a, i) => (
              <div key={i} className="bs-amend-item">
                <div className="bs-amend-top">
                  <span className="bs-amend-no">Дод. угода № {a.no}</span>
                  <span className="bs-amend-date td-mono">{fmtDate(a.date)}</span>
                </div>
                <div className="bs-amend-reason">{a.reason}</div>
                <ul className="bs-amend-changes">
                  {a.changes.map((ch, j) => <li key={j}>{ch}</li>)}
                </ul>
              </div>
            ))}
          </div>
        )}
      </div>
    );
  }

  // Перемикач ролі сторін у договорі
  function RoleConfig({ contract, onChange }) {
    const parties = window.contractParties(contract);
    const set = (patch) => {
      const cur = window.contractParties(contract);
      contract.parties = { ...cur, ...patch };
      if (patch.ourRole === "contractor" && cur.subject === "services") contract.parties.subject = "works";
      if (patch.ourRole === "executor") { contract.parties.subject = "services"; contract.parties.counterRole = "customer"; }
      onChange();
    };
    const Seg = ({ value, options, onPick }) => (
      <div className="vt-coord-seg bs-seg">
        {options.map(o => (
          <button key={o.value} type="button" className={`vt-seg-btn ${value === o.value ? "is-on" : ""}`}
            onClick={() => onPick(o.value)}>{o.label}</button>
        ))}
      </div>
    );
    return (
      <div className="bs-role">
        <div className="bs-role-field">
          <span className="bs-role-label">Наша роль</span>
          <Seg value={parties.ourRole} onPick={(v) => set({ ourRole: v })}
            options={[{ value: "executor", label: "Виконавець" }, { value: "contractor", label: "Підрядник" }]} />
        </div>
        {parties.ourRole === "contractor" && (
          <div className="bs-role-field">
            <span className="bs-role-label">Контрагент</span>
            <Seg value={parties.counterRole} onPick={(v) => set({ counterRole: v })}
              options={[{ value: "customer", label: "Замовник" }, { value: "genContractor", label: "Генпідрядник" }]} />
          </div>
        )}
        <div className="bs-role-field">
          <span className="bs-role-label">Предмет акта</span>
          <Seg value={parties.subject} onPick={(v) => set({ subject: v })}
            options={[{ value: "services", label: "Послуги" }, { value: "works", label: "Роботи" }]} />
        </div>
      </div>
    );
  }

  // Головний компонент — рендериться у розгорнутій картці договору
  function ContractSchedule({ contract, role, onPrintInvoice, onPrintAct }) {
    const [, force] = useState(0);
    const channel = window.billingChannel(contract);
    const ch = window.BILLING_CHANNEL[channel];
    const sum = window.contractBillingSummary(contract);

    const handle = (idx, key) => {
      const stage = contract.schedule[idx];
      if (key === "invoice") {
        // позначаємо рахунок виставленим + відкриваємо друковану форму
        if (!stage.invoiceNo) {
          const num = `${(contract.number || "").split("/")[0]}/${String(idx + 1).padStart(2, "0")}`;
          stage.invoiceNo = num; stage.invoiceDate = TODAY;
        }
        force(x => x + 1);
        onPrintInvoice && onPrintInvoice(window.draftInvoiceForContract(contract, idx));
      } else if (key === "act") {
        if (!stage.actDate) {
          const obj = window.getObject(contract.obj);
          const codeNum = obj && obj.code ? (obj.code.match(/(\d+)\s*$/) || [])[1] : (contract.number || "").split("/")[0];
          stage.actNo = `${codeNum}-АКТ-${String(idx + 1).padStart(2, "0")}`;
          stage.actDate = TODAY;
          if (!stage.factDate) stage.factDate = TODAY;
          stage.ready = true;
        }
        force(x => x + 1);
        onPrintAct && onPrintAct(window.draftActForContract(contract, idx));
      } else if (key === "pay") {
        stage.paidDate = TODAY;
        if (!stage.factDate) stage.factDate = stage.actDate || TODAY;
        force(x => x + 1);
      }
    };

    return (
      <div className="bs-wrap">
        <div className="bs-schedule-head">
          <span className="drawer-section-h" style={{ margin: 0 }}>Графік фінансування</span>
          <span className={`bs-channel tone-${ch.tone}`} title={ch.note}>
            <Ico name={ch.icon} size={13} /> {ch.label}
          </span>
        </div>

        <RoleConfig contract={contract} onChange={() => force(x => x + 1)} />

        <div className="bs-stages">
          {contract.schedule.map((s, idx) => (
            <StageRow key={idx} contract={contract} stage={s} idx={idx} role={role} onAction={handle} />
          ))}
        </div>

        <div className="bs-totals">
          <div className="bs-total-item is-paid"><span className="bs-total-dot"></span>Оплачено <b>{money(sum.paid)} ₴</b></div>
          {sum.billed > 0 && <div className="bs-total-item is-billed"><span className="bs-total-dot"></span>У роботі <b>{money(sum.billed)} ₴</b></div>}
          {sum.overdue > 0 && <div className="bs-total-item is-overdue"><span className="bs-total-dot"></span>Прострочено <b>{money(sum.overdue)} ₴</b></div>}
          {sum.planned > 0 && <div className="bs-total-item is-planned"><span className="bs-total-dot"></span>Заплановано <b>{money(sum.planned)} ₴</b></div>}
        </div>

        <AmendmentsBlock contract={contract} />
      </div>
    );
  }
  window.ContractSchedule = ContractSchedule;

})();
