# app/models/contract.py

from flask_login import UserMixin
from datetime import datetime
from app.extensions import db, login_manager
from werkzeug.security import generate_password_hash, check_password_hash
import random
import string
from dateutil.relativedelta import relativedelta


class Contract(db.Model):
    """مدل قرارداد بین کارفرما و عوامل اجرایی"""
    __tablename__ = 'contracts'
    __table_args__ = {'extend_existing': True}
    
    id = db.Column(db.Integer, primary_key=True)
    
    # روابط کلیدی
    project_id = db.Column(db.Integer, db.ForeignKey('projects.id'), nullable=False)
    employee_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    project_employee_id = db.Column(db.Integer, db.ForeignKey('project_employees.id'), nullable=True)
    
    # مبالغ
    total_amount = db.Column(db.Float, nullable=False)
    paid_amount = db.Column(db.Float, default=0)
    remaining_amount = db.Column(db.Float, default=0)
    
    # نوع پرداخت
    payment_method = db.Column(db.String(20), default='installment')  # monthly, installment, full
    payment_type = db.Column(db.String(20), default='monthly')  # monthly, installment, full
    number_of_installments = db.Column(db.Integer, default=1)
    payment_day_of_month = db.Column(db.Integer, default=1)
    
    # تاریخ‌ها
    start_date = db.Column(db.Date, nullable=False)
    end_date = db.Column(db.Date, nullable=True)
    
    # وضعیت
    is_active = db.Column(db.Boolean, default=True)
    payment_status = db.Column(db.String(20), default='pending')  # pending, active, completed, suspended
    
    # توضیحات
    description = db.Column(db.Text, nullable=True)
    
    # زمان‌ها
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    created_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
    
    # ========== روابط با نام‌های یکتا ==========
    # رابطه با Project
    project = db.relationship(
        'Project',
        foreign_keys=[project_id],
        backref='contracts_list'  # نام یکتا
    )
    
    # رابطه با User (Employee)
    employee = db.relationship(
        'User',
        foreign_keys=[employee_id],
        backref='user_contracts_list'  # نام یکتا
    )
    
    # رابطه با ProjectEmployee
    project_employee = db.relationship(
        'ProjectEmployee',
        foreign_keys=[project_employee_id],
        backref='employee_contracts_list'  # نام یکتا
    )
    
    # رابطه با Creator (User)
    creator = db.relationship(
        'User',
        foreign_keys=[created_by],
        backref='created_contracts_list'  # نام یکتا
    )
    
    # رابطه با ContractInstallment
    installments = db.relationship(
        'ContractInstallment',
        foreign_keys='ContractInstallment.contract_id',
        backref='parent_contract_ref',  # نام یکتا
        lazy=True,
        cascade='all, delete-orphan'
    )
    
    # رابطه با PaymentRequest
    payment_requests = db.relationship(
        'PaymentRequest',
        foreign_keys='PaymentRequest.contract_id',
        backref='source_contract_ref',  # نام یکتا
        lazy=True
    )
    # ...
    commission_items = db.relationship(
        'SystemCommission',
        foreign_keys='SystemCommission.contract_id',
        back_populates='contract'
    )
    
    # ========== متدها ==========
    
    def calculate_installments(self):
        """محاسبه اقساط قرارداد"""
        if self.payment_type == 'full':
            return [{
                'number': 1,
                'amount': self.total_amount,
                'due_date': self.start_date
            }]
        elif self.payment_type == 'monthly':
            months = 0
            current_date = self.start_date
            end = self.end_date or self.start_date + relativedelta(years=1)
            while current_date <= end:
                months += 1
                current_date += relativedelta(months=1)
            
            installment_amount = self.total_amount / months
            installments = []
            for i in range(months):
                due_date = self.start_date + relativedelta(months=i+1)
                due_date = due_date.replace(day=self.payment_day_of_month)
                installments.append({
                    'number': i+1,
                    'amount': installment_amount,
                    'due_date': due_date
                })
            return installments
        elif self.payment_type == 'installment':
            # اقساط دلخواه - باید در زمان ایجاد مشخص شوند
            return []
        else:
            return []
    
    def get_remaining_amount(self):
        """دریافت مبلغ باقیمانده"""
        return self.total_amount - self.paid_amount
    
    def get_paid_percentage(self):
        """دریافت درصد پرداخت شده"""
        if self.total_amount == 0:
            return 0
        return (self.paid_amount / self.total_amount) * 100
    
    def get_payment_status_display(self):
        """نمایش وضعیت پرداخت به فارسی"""
        status_map = {
            'pending': 'در انتظار',
            'active': 'فعال',
            'completed': 'تکمیل شده',
            'suspended': 'متوقف'
        }
        return status_map.get(self.payment_status, self.payment_status)
    
    def is_completed(self):
        """بررسی تکمیل بودن قرارداد"""
        return self.paid_amount >= self.total_amount
    
    def get_total_installments(self):
        """دریافت تعداد کل اقساط"""
        if self.payment_type == 'full':
            return 1
        elif self.payment_type == 'monthly':
            from dateutil.relativedelta import relativedelta
            months = 0
            current_date = self.start_date
            end = self.end_date or self.start_date + relativedelta(years=1)
            while current_date <= end:
                months += 1
                current_date += relativedelta(months=1)
            return months
        else:
            return self.number_of_installments or 1
    
    def get_paid_installments_count(self):
        """دریافت تعداد اقساط پرداخت شده"""
        return ContractInstallment.query.filter_by(
            contract_id=self.id,
            status='paid'
        ).count()
    
    def get_unpaid_installments(self):
        """دریافت اقساط پرداخت نشده"""
        return ContractInstallment.query.filter_by(
            contract_id=self.id,
            status='pending'
        ).order_by(ContractInstallment.due_date).all()
    
    def to_dict(self):
        """تبدیل به دیکشنری برای JSON"""
        return {
            'id': self.id,
            'project_id': self.project_id,
            'project_name': self.project.name if self.project else None,
            'employee_id': self.employee_id,
            'employee_name': self.employee.fullname if self.employee else None,
            'total_amount': self.total_amount,
            'total_amount_formatted': f"{self.total_amount:,.0f}",
            'paid_amount': self.paid_amount,
            'paid_amount_formatted': f"{self.paid_amount:,.0f}",
            'remaining_amount': self.remaining_amount,
            'remaining_amount_formatted': f"{self.remaining_amount:,.0f}",
            'paid_percentage': self.get_paid_percentage(),
            'payment_type': self.payment_type,
            'payment_status': self.payment_status,
            'payment_status_display': self.get_payment_status_display(),
            'start_date': self.start_date.strftime('%Y-%m-%d'),
            'end_date': self.end_date.strftime('%Y-%m-%d') if self.end_date else None,
            'is_active': self.is_active,
            'is_completed': self.is_completed(),
            'total_installments': self.get_total_installments(),
            'paid_installments': self.get_paid_installments_count(),
            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S')
        }
    
    def __repr__(self):
        return f'<Contract {self.id} - {self.total_amount} - {self.payment_status}>'


class ContractInstallment(db.Model):
    """مدل اقساط قرارداد"""
    __tablename__ = 'contract_installments'
    __table_args__ = {'extend_existing': True}
    
    id = db.Column(db.Integer, primary_key=True)
    contract_id = db.Column(db.Integer, db.ForeignKey('contracts.id'), nullable=False)
    
    installment_number = db.Column(db.Integer, nullable=False)
    amount = db.Column(db.Float, nullable=False)
    due_date = db.Column(db.Date, nullable=False)
    
    # وضعیت قسط
    status = db.Column(db.String(20), default='pending')  # pending, paid, overdue, cancelled
    paid_amount = db.Column(db.Float, default=0)
    paid_at = db.Column(db.DateTime, nullable=True)
    
    # اطلاعات پرداخت
    payment_request_id = db.Column(db.Integer, db.ForeignKey('payment_requests.id'), nullable=True)
    
    # توضیحات
    notes = db.Column(db.Text, nullable=True)
    
    # زمان‌ها
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # ========== روابط با نام‌های یکتا ==========
    
    
    # رابطه با PaymentRequest
    payment_request = db.relationship(
        'PaymentRequest',
        foreign_keys=[payment_request_id],
        backref='installment_payment_ref'  # نام یکتا
    )
    
    # ========== متدها ==========
    
    def mark_as_paid(self, payment_request_id=None):
        """علامت زدن قسط به عنوان پرداخت شده"""
        self.status = 'paid'
        self.paid_at = datetime.utcnow()
        if payment_request_id:
            self.payment_request_id = payment_request_id
    
    def mark_as_overdue(self):
        """علامت زدن قسط به عنوان معوق"""
        self.status = 'overdue'
    
    def is_overdue(self):
        """بررسی معوق بودن قسط"""
        return datetime.now().date() > self.due_date and self.status == 'pending'
    
    def get_status_display(self):
        """نمایش وضعیت به فارسی"""
        status_map = {
            'pending': 'در انتظار',
            'paid': 'پرداخت شده',
            'overdue': 'معوق',
            'cancelled': 'لغو شده'
        }
        return status_map.get(self.status, self.status)
    
    def to_dict(self):
        """تبدیل به دیکشنری برای JSON"""
        return {
            'id': self.id,
            'contract_id': self.contract_id,
            'installment_number': self.installment_number,
            'amount': self.amount,
            'amount_formatted': f"{self.amount:,.0f}",
            'due_date': self.due_date.strftime('%Y-%m-%d'),
            'status': self.status,
            'status_display': self.get_status_display(),
            'paid_amount': self.paid_amount,
            'paid_at': self.paid_at.strftime('%Y-%m-%d %H:%M:%S') if self.paid_at else None,
            'is_overdue': self.is_overdue(),
            'payment_request_id': self.payment_request_id,
            'notes': self.notes
        }
    
    def __repr__(self):
        return f'<ContractInstallment {self.installment_number} - {self.amount} - {self.status}>'