"""
Invoice Model - Billing invoices
"""
from sqlalchemy import Column, String, Integer, ForeignKey, Numeric, Date, Text, JSON, DateTime
from sqlalchemy.orm import relationship
from enum import Enum
from datetime import date

from app.models.base import BaseModel


class InvoiceStatus(str, Enum):
    DRAFT = "draft"
    PENDING = "pending"
    PAID = "paid"
    OVERDUE = "overdue"
    CANCELLED = "cancelled"
    REFUNDED = "refunded"
    PARTIALLY_PAID = "partially_paid"


class Invoice(BaseModel):
    """
    Invoice model for billing
    """
    __tablename__ = "invoices"

    # Client
    client_id = Column(Integer, ForeignKey("clients.id", ondelete="CASCADE"), nullable=False, index=True)

    # Invoice Info
    invoice_number = Column(String(50), unique=True, nullable=False, index=True)
    invoice_date = Column(Date, nullable=False, default=date.today)
    due_date = Column(Date, nullable=False)

    # Billing Period
    billing_period_start = Column(Date, nullable=False)
    billing_period_end = Column(Date, nullable=False)

    # Amounts
    subtotal = Column(Numeric(10, 2), nullable=False)
    discount_amount = Column(Numeric(10, 2), default=0)
    discount_percentage = Column(Numeric(5, 2), default=0)
    tax_rate = Column(Numeric(5, 2), default=18)  # GST 18%
    tax_amount = Column(Numeric(10, 2), nullable=False)
    total_amount = Column(Numeric(10, 2), nullable=False)
    amount_paid = Column(Numeric(10, 2), default=0)
    amount_due = Column(Numeric(10, 2), nullable=False)
    currency = Column(String(3), default="INR")

    # Status
    status = Column(String(50), default=InvoiceStatus.PENDING, nullable=False)

    # Line Items
    line_items = Column(JSON, default=[])
    # Example: [
    #   {"description": "Chatbot Pro Plan", "quantity": 1, "unit_price": 4999, "amount": 4999},
    #   {"description": "Document Intelligence", "quantity": 1, "unit_price": 2999, "amount": 2999},
    #   {"description": "Additional API Calls (5000)", "quantity": 5000, "unit_price": 0.10, "amount": 500}
    # ]

    # Payment
    payment_method = Column(String(50), nullable=True)  # stripe, razorpay, bank_transfer
    payment_reference = Column(String(255), nullable=True)
    stripe_invoice_id = Column(String(100), nullable=True)
    razorpay_invoice_id = Column(String(100), nullable=True)
    paid_at = Column(DateTime(timezone=True), nullable=True)

    # PDF
    pdf_url = Column(String(500), nullable=True)

    # Notes
    notes = Column(Text, nullable=True)
    internal_notes = Column(Text, nullable=True)

    # Metadata
    extra_data = Column("metadata", JSON, default={})  # Renamed to avoid SQLAlchemy reserved word

    # Relationships
    client = relationship("Client", back_populates="invoices")

    def __repr__(self):
        return f"<Invoice {self.invoice_number}>"

    @property
    def is_paid(self) -> bool:
        return self.status == InvoiceStatus.PAID

    @property
    def is_overdue(self) -> bool:
        if self.status == InvoiceStatus.PAID:
            return False
        return date.today() > self.due_date

    @property
    def balance_due(self) -> float:
        return float(self.amount_due) - float(self.amount_paid or 0)

    @staticmethod
    def generate_invoice_number(client_id: int, count: int) -> str:
        """Generate invoice number like INV-2024-001234"""
        year = date.today().year
        return f"INV-{year}-{str(count).zfill(6)}"
