# app/models/deposit.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
import hashlib


class Deposit(db.Model):
    """واریز کارفرما به حساب سامانه"""
    __tablename__ = 'deposits'
    __table_args__ = {'extend_existing': True}
    
    id = db.Column(db.Integer, primary_key=True)
    
    # روابط کلیدی
    escrow_id = db.Column(db.Integer, db.ForeignKey('escrow_accounts.id'), nullable=False)
    project_id = db.Column(db.Integer, db.ForeignKey('projects.id'), nullable=False)
    employer_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    contract_id = db.Column(db.Integer, db.ForeignKey('contracts.id'), nullable=True)
    
    # مبالغ
    amount = db.Column(db.Float, nullable=False)
    installment_number = db.Column(db.Integer, default=1)
    
    # اطلاعات واریز
    tracking_code = db.Column(db.String(100), unique=True, nullable=False)
    payment_date = db.Column(db.Date, nullable=False)
    receipt_image = db.Column(db.String(200), nullable=True)
    
    # اطلاعات بانکی مبدأ
    source_bank = db.Column(db.String(100), nullable=True)
    source_account = db.Column(db.String(50), nullable=True)
    source_card_number = db.Column(db.String(20), nullable=True)  # شماره کارت مبدأ
    
    # اطلاعات بانکی مقصد (حساب سامانه)
    destination_account_id = db.Column(db.Integer, db.ForeignKey('system_bank_accounts.id'), nullable=True)  # تغییر به nullable=True
    
    # توضیحات
    description = db.Column(db.Text, nullable=True)
    rejection_reason = db.Column(db.Text, nullable=True)  # دلیل رد شدن
    
    # وضعیت
    status = db.Column(db.String(20), default='pending')  # pending, verified, rejected, cancelled
    admin_verified = db.Column(db.Boolean, default=False)
    admin_verified_at = db.Column(db.DateTime, nullable=True)
    admin_verified_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
    
    # زمان‌ها
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # ========== روابط با نام‌های یکتا ==========
    
    # رابطه با EscrowAccount
    escrow = db.relationship(
        'EscrowAccount',
        foreign_keys=[escrow_id],
        backref='deposits_list'
    )
    
    # رابطه با Project
    project = db.relationship(
        'Project',
        foreign_keys=[project_id],
        backref='project_deposits_list'
    )
    
    # رابطه با User (Employer)
    employer = db.relationship(
        'User',
        foreign_keys=[employer_id],
        backref='user_deposits_list'
    )
    
    # رابطه با Contract
    contract = db.relationship(
        'Contract',
        foreign_keys=[contract_id],
        backref='contract_deposits_list'
    )
    
    # ======== اصلاح رابطه با SystemBankAccount ========
    # استفاده از backref با نام یکتا
    destination_account = db.relationship(
        'SystemBankAccount',
        foreign_keys=[destination_account_id],
        backref='deposits_to_account_ref'  # تغییر نام
    )
    
    # رابطه با User (Verifier - Admin)
    verifier = db.relationship(
        'User',
        foreign_keys=[admin_verified_by],
        backref='verified_deposits_list'
    )
    
    # رابطه با SystemCommission
    commission_records = db.relationship(
        'SystemCommission',
        foreign_keys='SystemCommission.deposit_id',
        backref='deposit_commission_ref',
        lazy='dynamic'
    )
    
    # رابطه با PaymentRequest (از طریق releases)
    payment_releases = db.relationship(
        'PaymentRequest',
        foreign_keys='PaymentRequest.deposit_id',
        backref='deposit_ref',
        lazy='dynamic'
    )
    
    # ========== متدها ==========
    
    def generate_tracking_code(self):
        """تولید کد پیگیری یکتا"""
        code_string = f"{self.project_id}{self.employer_id}{self.amount}{datetime.now().timestamp()}{random.randint(1000, 9999)}"
        self.tracking_code = hashlib.md5(code_string.encode()).hexdigest()[:16].upper()
        return self.tracking_code
    
    def verify(self, admin_id):
        """تایید واریز توسط ادمین"""
        if self.status != 'pending':
            raise ValueError(f"واریز با وضعیت {self.status} قابل تایید نیست")
        
        self.status = 'verified'
        self.admin_verified = True
        self.admin_verified_at = datetime.utcnow()
        self.admin_verified_by = admin_id
        
        # افزایش موجودی صندوق امانی مرکزی
        if self.escrow:
            self.escrow.deposit(
                amount=self.amount,
                tracking_code=self.tracking_code,
                employer_id=self.employer_id,
                project_id=self.project_id,
                source_bank=self.source_bank,
                source_account=self.source_account,
                description=self.description
            )
        
        # ثبت لاگ
        from app.models import AuditLog
        AuditLog.log_action(
            user_id=admin_id,
            action='verify',
            entity_type='deposit',
            entity_id=self.id,
            details=f'واریز به مبلغ {self.amount:,.0f} تومان با کد پیگیری {self.tracking_code} تایید شد'
        )
        
        return True
    
    def reject(self, admin_id, reason=None):
        """رد واریز توسط ادمین"""
        if self.status != 'pending':
            raise ValueError(f"واریز با وضعیت {self.status} قابل رد نیست")
        
        self.status = 'rejected'
        self.admin_verified = False
        self.admin_verified_at = datetime.utcnow()
        self.admin_verified_by = admin_id
        if reason:
            self.rejection_reason = reason
        
        # ثبت لاگ
        from app.models import AuditLog
        AuditLog.log_action(
            user_id=admin_id,
            action='reject',
            entity_type='deposit',
            entity_id=self.id,
            details=f'واریز به مبلغ {self.amount:,.0f} تومان رد شد. دلیل: {reason or "نامشخص"}'
        )
        
        return True
    
    def cancel(self, admin_id, reason=None):
        """لغو واریز توسط ادمین"""
        if self.status in ['verified', 'rejected']:
            raise ValueError(f"واریز با وضعیت {self.status} قابل لغو نیست")
        
        self.status = 'cancelled'
        if reason:
            self.rejection_reason = reason
        
        # ثبت لاگ
        from app.models import AuditLog
        AuditLog.log_action(
            user_id=admin_id,
            action='cancel',
            entity_type='deposit',
            entity_id=self.id,
            details=f'واریز به مبلغ {self.amount:,.0f} تومان لغو شد. دلیل: {reason or "نامشخص"}'
        )
        
        return True
    
    def get_status_display(self):
        """نمایش وضعیت به فارسی"""
        status_map = {
            'pending': 'در انتظار تایید',
            'verified': 'تایید شده',
            'rejected': 'رد شده',
            'cancelled': 'لغو شده'
        }
        return status_map.get(self.status, self.status)
    
    def get_amount_formatted(self):
        """دریافت مبلغ به صورت فرمت شده"""
        return f"{self.amount:,.0f}"
    
    def is_pending(self):
        """بررسی در انتظار بودن"""
        return self.status == 'pending'
    
    def is_verified(self):
        """بررسی تایید شده بودن"""
        return self.status == 'verified'
    
    def to_dict(self):
        """تبدیل به دیکشنری برای JSON"""
        return {
            'id': self.id,
            'project_id': self.project_id,
            'project_name': self.project.name if self.project else None,
            'employer_id': self.employer_id,
            'employer_name': self.employer.fullname if self.employer else None,
            'contract_id': self.contract_id,
            'amount': self.amount,
            'amount_formatted': self.get_amount_formatted(),
            'installment_number': self.installment_number,
            'tracking_code': self.tracking_code,
            'payment_date': self.payment_date.strftime('%Y-%m-%d'),
            'receipt_image': self.receipt_image,
            'source_bank': self.source_bank,
            'source_account': self.source_account,
            'destination_account': self.destination_account.account_number if self.destination_account else None,
            'destination_bank': self.destination_account.bank_name if self.destination_account else None,
            'description': self.description,
            'rejection_reason': self.rejection_reason,
            'status': self.status,
            'status_display': self.get_status_display(),
            'admin_verified': self.admin_verified,
            'admin_verified_at': self.admin_verified_at.strftime('%Y-%m-%d %H:%M:%S') if self.admin_verified_at else None,
            'verifier_name': self.verifier.fullname if self.verifier else None,
            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
            'is_pending': self.is_pending(),
            'is_verified': self.is_verified()
        }
    
    def __repr__(self):
        return f'<Deposit {self.tracking_code} - {self.amount} - {self.status}>'