import re
from datetime import datetime
from pathlib import Path
from typing import List

import pdfplumber

from backend.parsers.base import BaseBankParser, ParsedTransaction


def _normalize_amount(s: str) -> float:
    """Пробелы убрать, запятая — десятичный разделитель."""
    return float(s.replace("\u00a0", " ").replace(" ", "").replace(",", "."))


def _parse_datetime_s(date_str: str, time_str: str) -> str:
    """DD.MM.YYYY + HH:MM -> ISO."""
    try:
        part = date_str.strip() + " " + (time_str or "00:00").strip()
        dt = datetime.strptime(part, "%d.%m.%Y %H:%M")
        return dt.strftime("%Y-%m-%dT%H:%M:%S")
    except ValueError:
        return date_str.strip()[:10].replace(".", "-") + "T00:00:00"


class BankSParser(BaseBankParser):
    """Парсер выписок Сбербанка. Файлы С-MM-YY.pdf."""

    # Первая строка: дата время код_авторизации категория сумма остаток (сумма с + = приход, без = расход)
    ROW_RE = re.compile(
        r"^(\d{2}\.\d{2}\.\d{4})\s+(\d{1,2}:\d{2})\s+(\d{6})\s+(.+?)\s+([+-]?[\d\s]+,\d{2})\s+([\d\s]+,\d{2})\s*$",
        re.UNICODE,
    )
    # Вторая строка: дата описание ... Операция по (перенос)
    DESC_LINE1_RE = re.compile(r"^(\d{2}\.\d{2}\.\d{4})\s+(.+?)\s+Операция по\s*$", re.UNICODE)
    # Третья строка: карте ****0566
    CARD_LINE_RE = re.compile(r"^карте\s+\*\*\*\*(\d{4})\s*$", re.UNICODE)

    def can_parse(self, filename: str) -> bool:
        name = Path(filename).name
        return name.startswith("С-") and name.lower().endswith(".pdf")

    def parse(self, file_path: str) -> List[ParsedTransaction]:
        result: List[ParsedTransaction] = []
        with pdfplumber.open(file_path) as pdf:
            lines: List[str] = []
            for page in pdf.pages:
                text = page.extract_text()
                if text:
                    lines.extend(text.split("\n"))

        i = 0
        while i < len(lines):
            line = lines[i].strip()
            m = self.ROW_RE.match(line)
            if m:
                date_op, time_op, _code, category, amount_str, _balance = m.groups()
                amount = _normalize_amount(amount_str)
                if not amount_str.strip().startswith("+"):
                    amount = -amount
                desc_extra = ""
                card_tail = ""
                if i + 1 < len(lines):
                    d1 = self.DESC_LINE1_RE.match(lines[i + 1].strip())
                    if d1:
                        desc_extra = " " + d1.group(2).strip()
                        i += 1
                        if i + 1 < len(lines):
                            c2 = self.CARD_LINE_RE.match(lines[i + 1].strip())
                            if c2:
                                card_tail = c2.group(1)
                                i += 1
                if not card_tail:
                    card_tail = "0000"
                description = (category + desc_extra).strip()
                result.append(
                    ParsedTransaction(
                        operation_date=_parse_datetime_s(date_op, time_op),
                        debit_date=None,
                        amount=amount,
                        amount_card_currency=None,
                        description=description,
                        card_tail=card_tail,
                    )
                )
            i += 1
        return result
