"""Shared fixtures for B-44 ledger / manual / position tests."""

from __future__ import annotations

from pathlib import Path
import sqlite3
import tempfile
import unittest

from bank_importer import auth, matching, master_data
from bank_importer.db import connect, migrate, utc_now


class LedgerBase(unittest.TestCase):
    def setUp(self) -> None:
        self.temp_dir = tempfile.TemporaryDirectory()
        self.addCleanup(self.temp_dir.cleanup)
        root = Path(self.temp_dir.name)
        self.db_path = root / "app.db"
        self.connection = connect(self.db_path)
        self.addCleanup(self.connection.close)
        migrate(self.connection)
        self.admin = self._admin()
        self.company_a = self._company("甲公司")
        self.company_b = self._company("乙公司")
        self.company_c = self._company("丙公司")
        self.account_a = self._approved_account(self.company_a, "6222000000000001")
        self.account_b = self._approved_account(self.company_b, "6222000000000002")

    def _admin(self):
        auth.create_user(self.connection, "admin-u", "AdminPass123", "admin")
        return self.connection.execute(
            "SELECT * FROM users WHERE username = 'admin-u'"
        ).fetchone()

    def _company(self, name: str) -> int:
        with self.connection:
            cursor = self.connection.execute(
                "INSERT INTO companies (name, created_at, updated_at) VALUES (?, ?, ?)",
                (name, utc_now(), utc_now()),
            )
        return int(cursor.lastrowid)

    def _approved_account(self, company_id: int, number: str, start: str = "2026-01-01"):
        account = master_data.submit_bank_account(
            self.connection, company_id=company_id, bank_name="中信银行",
            account_type="基本户", account_number=number, start_date=start,
            actor=None,
        )
        return master_data.review_bank_account(
            self.connection, account["id"], "approve", None, self.admin,
            effective_from=start,
        )

    def add_row(
        self,
        company_id: int,
        *,
        own_account: str,
        cp_account: str | None = None,
        income: str = "0",
        expense: str = "0",
        at: str = "2026-01-05T10:00:00",
        currency: str = "CNY",
        reference: str | None = None,
        summary: str | None = None,
        purpose: str | None = None,
    ) -> int:
        with self.connection:
            cursor = self.connection.execute(
                """
                INSERT INTO source_files (sha256, original_filename, size_bytes, storage_path, created_at)
                VALUES (?, '测试.xlsx', 1, 'data/files/测试.xlsx', ?)
                """,
                (utc_now(), utc_now()),
            )
            source_file_id = int(cursor.lastrowid)
            cursor = self.connection.execute(
                """
                INSERT INTO import_batches (source_file_id, status, company_id, created_at, updated_at)
                VALUES (?, 'parsing', ?, ?, ?)
                """,
                (source_file_id, company_id, utc_now(), utc_now()),
            )
            batch_id = int(cursor.lastrowid)
            cursor = self.connection.execute(
                """
                INSERT INTO sheet_batches (
                    import_batch_id, sheet_name, bank_name, template_id, template_version,
                    header_row, own_account, own_name, period_start, period_end,
                    transaction_count, warnings, created_at
                ) VALUES (?, '流水', '测试银行', 'test-v1', 1, 1, NULL, NULL, NULL, NULL, 1, '[]', ?)
                """,
                (batch_id, utc_now()),
            )
            sheet_batch_id = int(cursor.lastrowid)
            self.connection.execute(
                """
                INSERT INTO sheet_reviews (
                    import_batch_id, sheet_name, outcome, sheet_batch_id,
                    review_status, created_at
                ) VALUES (?, '流水', 'parsed', ?, 'confirmed', ?)
                """,
                (batch_id, sheet_batch_id, utc_now()),
            )
            cursor = self.connection.execute(
                """
                INSERT INTO source_rows (
                    sheet_batch_id, source_row, transaction_at, income, expense, balance,
                    own_account, own_name, counterparty_account, counterparty_name,
                    counterparty_bank, summary, purpose, reference, currency, created_at
                ) VALUES (?, 1, ?, ?, ?, NULL, ?, '测试', ?, '对方', NULL, ?, ?, ?, ?, ?)
                """,
                (
                    sheet_batch_id, at, income, expense, own_account,
                    cp_account, summary, purpose, reference, currency, utc_now(),
                ),
            )
        return int(cursor.lastrowid)

    def pair(
        self,
        payer: int,
        payee: int,
        amount: str,
        at: str = "2026-01-05T10:00:00",
        *,
        currency: str = "CNY",
        summary: str = "借款",
        purpose: str = "往来款",
    ) -> tuple[int, int]:
        """Create a mirrored A/B pair and reconcile into an eligible event."""
        payer_account = self._account_of(payer)
        payee_account = self._account_of(payee)
        row_payer = self.add_row(
            payer, own_account=payer_account, cp_account=payee_account,
            expense=amount, at=at, currency=currency, summary=summary, purpose=purpose,
        )
        row_payee = self.add_row(
            payee, own_account=payee_account, cp_account=payer_account,
            income=amount, at=at.replace("T10:", "T11:"), currency=currency,
            summary=summary, purpose=purpose,
        )
        matching.reconcile_rows(self.connection, [row_payer, row_payee])
        return row_payer, row_payee

    def _account_of(self, company_id: int) -> str:
        if company_id == self.company_a:
            return self.account_a["account_number"]
        if company_id == self.company_b:
            return self.account_b["account_number"]
        return "6222000000000005"

    def eligible(self) -> list[sqlite3.Row]:
        return matching.eligible_intercompany_events(self.connection)

    def ledger_events(self) -> list[sqlite3.Row]:
        return self.connection.execute(
            "SELECT * FROM ledger_events ORDER BY id"
        ).fetchall()

    def current(self, ledger_event_id: int) -> sqlite3.Row | None:
        return self.connection.execute(
            """
            SELECT r.* FROM current_ledger_event_revisions c
            JOIN ledger_event_revisions r ON r.id = c.revision_id
            WHERE c.ledger_event_id = ?
            """,
            (ledger_event_id,),
        ).fetchone()

    def position_events(self) -> list[sqlite3.Row]:
        return self.connection.execute(
            "SELECT * FROM eligible_position_events ORDER BY ledger_event_id"
        ).fetchall()
