"""Shared pytest fixtures and helpers.

Everything here is self-contained — tiny in-memory workbooks and hand-built
invoice lists — so the suite runs with only ``openpyxl`` + ``pytest`` installed
(no strands / DB / Odoo). The ``service`` directory is put on ``sys.path`` so
``import app...`` resolves regardless of the working directory pytest is run from.
"""

from __future__ import annotations

import sys
from datetime import date
from pathlib import Path

import pytest
from openpyxl import Workbook

SERVICE_ROOT = Path(__file__).resolve().parent.parent
if str(SERVICE_ROOT) not in sys.path:
    sys.path.insert(0, str(SERVICE_ROOT))

from app.matching.models import Invoice, MatchSettings  # noqa: E402

# Month columns begin at column G (7), matching sample_data/generate_sample.py.
MONTH_START_COL = 7


@pytest.fixture
def settings() -> MatchSettings:
    """Default tolerances for Oct-2026 reconciliation."""
    return MatchSettings(
        abs_tolerance=1.00,
        rel_tolerance=0.005,
        rounding=2,
        unresolved_policy="amber",
        period_year=2026,
        period_month=10,
    )


def make_invoice(
    odoo_id: int,
    customer: str,
    amount: float,
    *,
    customer_id: int | None = None,
    day: int = 15,
    number: str | None = None,
    sent: bool = True,
) -> Invoice:
    """Construct an Invoice for 2026-10 with sensible defaults."""
    return Invoice(
        odoo_id=odoo_id,
        number=number or f"INV/{odoo_id}",
        customer=customer,
        invoice_date=date(2026, 10, day),
        amount_untaxed=amount,
        amount_total=round(amount * 1.15, 2),
        sent=sent,
        odoo_customer_id=customer_id,
    )


def build_workbook(
    tmp_path: Path,
    rows: list[tuple[int, str | None, float | None, object]],
    *,
    months: list[date] | None = None,
    sheet_name: str = "projects",
) -> Path:
    """Write a tiny ``projects`` workbook and return its path.

    Each ``rows`` entry is ``(row_number, name, value_col_F, oct_amount)``. The
    header row 1 carries the month dates (real datetime cells by default); the
    Oct-2026 amount is written into the located month column.
    """
    months = months or [date(2026, 9, 1), date(2026, 10, 1), date(2026, 11, 1)]
    wb = Workbook()
    ws = wb.active
    ws.title = sheet_name

    ws.cell(row=1, column=2, value="Client / Project")
    ws.cell(row=1, column=6, value="Value")
    for offset, m in enumerate(months):
        ws.cell(row=1, column=MONTH_START_COL + offset, value=m)
    oct_col = MONTH_START_COL + months.index(date(2026, 10, 1))

    for row_number, name, value, oct_amount in rows:
        if name is not None:
            ws.cell(row=row_number, column=2, value=name)
        if value is not None:
            ws.cell(row=row_number, column=6, value=value)
        if oct_amount is not None:
            ws.cell(row=row_number, column=oct_col, value=oct_amount)

    path = tmp_path / "planning.xlsx"
    wb.save(path)
    return path
