"""Şekli eksiklik giderme — "Değişiklik Gösteren Evrak" DOCX üreticisi.

Patent ofisinin şekli inceleme/itiraz yazısına cevaben, başvuru sahibinin
sunması gereken resmî değişiklik dilekçesini üretir. Üç ofis desteklenir:

- TR (TürkPatent): "Tarifname Takımında Yapılan Değişikliğin Gösterildiği
  Evrak" — 6769 sayılı SMK kapsamında.
- EP (EPO): "Amendments to the application" — Rule 137 EPC; her değişiklik
  için başvurunun ilk halindeki dayanağı (basis) belirtilir.
- US (USPTO): "Amendment" — MPEP 714; yapılan değişiklikler ve dayanakları.

Tüm metinler ofise göre `_TEMPLATES`'ten gelir; DOCX biçim helper'ları
(A4, Times New Roman 12pt, 20/25/20/20 mm kenar boşlukları, satır numarası
yok) ortaktır.
"""

from __future__ import annotations

import io
from enum import StrEnum

from docx import Document
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_LINE_SPACING
from docx.shared import Pt
from pydantic import BaseModel, Field

from app.services.docx.builder import (
    _add_page_number,
    _set_base_style,
    _set_margins,
)


class AmendmentJurisdiction(StrEnum):
    """Değişiklik evrakının hazırlandığı patent ofisi."""

    TR = "TR"
    EP = "EP"
    US = "US"


class AmendmentItem(BaseModel):
    """Giderilen tek bir eksiklik / yapılan tek bir değişiklik."""

    finding_title: str = Field(..., description="Şekli inceleme tespiti")
    change_made: str = Field(..., description="Yapılan değişikliğin açıklaması")


class TermChange(BaseModel):
    """Yabancı terim eski→yeni karşılaştırması (yalnızca TR)."""

    before: str
    after: str


class AmendmentInput(BaseModel):
    """Değişiklik evrakı üretimi için girdi."""

    application_number: str = Field(..., description="Başvuru numarası")
    application_date: str = Field(default="", description="Başvuru tarihi")
    invention_title: str = Field(..., description="Buluş başlığı")
    applicant_name: str = Field(default="", description="Başvuru sahibi")
    office_letter_ref: str = Field(
        default="", description="İlgili şekli inceleme/itiraz yazısı sayı/tarih"
    )
    jurisdiction: AmendmentJurisdiction = Field(
        default=AmendmentJurisdiction.TR,
        description="Hedef patent ofisi — evrak dilini ve formatını belirler",
    )
    items: list[AmendmentItem] = Field(
        default_factory=list, description="Giderilen eksiklikler / değişiklikler"
    )
    term_changes: list[TermChange] = Field(
        default_factory=list,
        description="Yabancı terim eski→yeni tablosu (yalnızca TR)",
    )


# --------------------------------------------------------------------------
# Ofis-özgü metin şablonları
# --------------------------------------------------------------------------
# Her şablon: evrak başlığı, bölüm başlıkları, alan etiketleri ve sabit
# açıklama/sonuç paragrafları. {n} alanları item numarasıyla doldurulur.

_TEMPLATES: dict[AmendmentJurisdiction, dict[str, str]] = {
    AmendmentJurisdiction.TR: {
        "doc_title": "TARİFNAME TAKIMINDA YAPILAN DEĞİŞİKLİĞİN GÖSTERİLDİĞİ EVRAK",
        "info_heading": "Başvuru Bilgileri",
        "label_app_number": "Başvuru Numarası",
        "label_app_date": "Başvuru Tarihi",
        "label_title": "Buluş Başlığı",
        "label_applicant": "Başvuru Sahibi",
        "label_letter": "İlgili Yazı",
        "explanation_heading": "Açıklama",
        "explanation": (
            "Kurumunuzun şekli inceleme yazısında tespit edilen eksiklikler, "
            "6769 sayılı Sınai Mülkiyet Kanunu ve ilgili Yönetmelik "
            "hükümlerine uygun olarak giderilmiş olup, yapılan değişiklikler "
            "aşağıda madde madde gösterilmiştir. Yapılan tüm değişiklikler "
            "yalnızca şekli niteliktedir; başvurunun ilk halinin teknik "
            "kapsamı genişletilmemiş veya daraltılmamış, buluşun teknik "
            "içeriği korunmuştur."
        ),
        "item_change_label": "Yapılan değişiklik",
        "conclusion_heading": "Sonuç",
        "conclusion": (
            "Yukarıda açıklanan şekli eksikliklerin tamamı giderilmiştir. "
            "Düzeltilmiş başvuru unsurları ekte sunulmuştur. Yapılan "
            "değişiklikler şekli niteliktedir ve başvurunun ilk halinin "
            "kapsamını aşmamaktadır."
        ),
    },
    AmendmentJurisdiction.EP: {
        "doc_title": "AMENDMENTS TO THE EUROPEAN PATENT APPLICATION",
        "info_heading": "Application Details",
        "label_app_number": "Application Number",
        "label_app_date": "Filing Date",
        "label_title": "Title of Invention",
        "label_applicant": "Applicant",
        "label_letter": "Communication Reference",
        "explanation_heading": "Statement of Amendments",
        "explanation": (
            "In response to the communication of the European Patent "
            "Office, the application documents are amended as set out below. "
            "Pursuant to Rule 137 EPC, each amendment and its basis in the "
            "application as originally filed are indicated. The amendments "
            "do not extend the subject-matter of the application beyond the "
            "content of the application as filed (Article 123(2) EPC)."
        ),
        "item_change_label": "Amendment made",
        "conclusion_heading": "Conclusion",
        "conclusion": (
            "The amendments set out above address the deficiencies raised. "
            "The amended application documents are enclosed. The amendments "
            "comply with Article 123(2) EPC and do not extend the subject-"
            "matter beyond the content of the application as originally "
            "filed."
        ),
    },
    AmendmentJurisdiction.US: {
        "doc_title": "AMENDMENT",
        "info_heading": "Application Information",
        "label_app_number": "Application No.",
        "label_app_date": "Filing Date",
        "label_title": "Title of Invention",
        "label_applicant": "Applicant",
        "label_letter": "In Reply to Office Action",
        "explanation_heading": "Remarks",
        "explanation": (
            "In response to the Office Action, the application is amended as "
            "set out below. Each amendment and its support in the "
            "specification as originally filed are identified. No new matter "
            "is added by these amendments (35 U.S.C. 132; 37 CFR 1.121)."
        ),
        "item_change_label": "Amendment made",
        "conclusion_heading": "Conclusion",
        "conclusion": (
            "The amendments set out above are believed to place the "
            "application in condition for allowance. No new matter has been "
            "introduced. Reconsideration and allowance of the application "
            "are respectfully requested."
        ),
    },
}


# --------------------------------------------------------------------------
# DOCX biçim helper'ları (ofiseden bağımsız)
# --------------------------------------------------------------------------

def _new_letter_doc():
    """Dilekçe tipi DOCX: builder formatı, satır numarası YOK."""
    doc = Document()
    _set_base_style(doc)
    section = doc.sections[0]
    _set_margins(section)
    _add_page_number(section.footer)
    return doc


def _heading(doc, text: str, *, level: int = 1, center: bool = False):
    p = doc.add_paragraph()
    if center:
        p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    p.paragraph_format.space_before = Pt(12)
    p.paragraph_format.space_after = Pt(6)
    run = p.add_run(text)
    run.bold = True
    run.font.name = "Times New Roman"
    run.font.size = Pt(14) if level == 1 else Pt(12)
    return p


def _para(doc, text: str, *, justify: bool = True, bold: bool = False):
    p = doc.add_paragraph()
    p.alignment = (
        WD_ALIGN_PARAGRAPH.JUSTIFY if justify else WD_ALIGN_PARAGRAPH.LEFT
    )
    pf = p.paragraph_format
    pf.line_spacing_rule = WD_LINE_SPACING.ONE_POINT_FIVE
    pf.space_after = Pt(6)
    run = p.add_run(text)
    run.font.name = "Times New Roman"
    run.font.size = Pt(12)
    run.bold = bold
    return p


def _term_table(doc, changes: list[TermChange]) -> None:
    """Yabancı terim eski→yeni karşılaştırma tablosu (yalnızca TR)."""
    rows = [("Yabancı İfade (İlk Hal)", "Türkçe Karşılığı ile Düzeltilmiş Hal")]
    rows += [(c.before, c.after) for c in changes]
    table = doc.add_table(rows=len(rows), cols=2)
    table.style = "Table Grid"
    for ri, (left, right) in enumerate(rows):
        for ci, val in enumerate((left, right)):
            cell = table.cell(ri, ci)
            cell.text = ""
            run = cell.paragraphs[0].add_run(val)
            run.font.name = "Times New Roman"
            run.font.size = Pt(11)
            if ri == 0:
                run.bold = True


def build_amendment_docx(data: AmendmentInput) -> bytes:
    """Değişiklik gösteren evrakı in-memory DOCX olarak üretir.

    Evrakın dili ve hukuki dayanakları `data.jurisdiction`'a göre seçilir.
    """
    tpl = _TEMPLATES[data.jurisdiction]
    doc = _new_letter_doc()

    _heading(doc, tpl["doc_title"], level=1, center=True)

    # --- Başvuru bilgileri ---
    _heading(doc, tpl["info_heading"], level=2)
    _para(doc, f"{tpl['label_app_number']}: {data.application_number}")
    if data.application_date:
        _para(doc, f"{tpl['label_app_date']}: {data.application_date}")
    _para(doc, f"{tpl['label_title']}: {data.invention_title}")
    if data.applicant_name:
        _para(doc, f"{tpl['label_applicant']}: {data.applicant_name}")
    if data.office_letter_ref:
        _para(doc, f"{tpl['label_letter']}: {data.office_letter_ref}")

    # --- Açıklama ---
    _heading(doc, tpl["explanation_heading"], level=2)
    _para(doc, tpl["explanation"])

    # --- Giderilen eksiklikler / yapılan değişiklikler ---
    for idx, item in enumerate(data.items, start=1):
        _heading(doc, f"{idx}. {item.finding_title}", level=2)
        _para(doc, f"{tpl['item_change_label']}: {item.change_made}")

    # --- Yabancı terim tablosu (yalnızca TürkPatent) ---
    if data.jurisdiction == AmendmentJurisdiction.TR and data.term_changes:
        _heading(doc, "Yabancı İfadelerin Türkçe Karşılıkları", level=2)
        _para(
            doc,
            "Teknik terim niteliği taşımayan yabancı dildeki ifadelere "
            "Türkçe karşılıkları eklenmiştir. İfadenin ilk geçtiği yerde "
            "Türkçe karşılığı yazılmış, özgün yabancı ifade parantez içinde "
            "belirtilmiştir. Örnek değişiklikler aşağıdaki tabloda "
            "gösterilmiştir.",
        )
        _term_table(doc, data.term_changes)

    # --- Sonuç ---
    _heading(doc, tpl["conclusion_heading"], level=2)
    _para(doc, tpl["conclusion"])

    buffer = io.BytesIO()
    doc.save(buffer)
    return buffer.getvalue()
