# app/models/commission_request.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


class CommissionRequest(db.Model):
    """مدل درخواست کمیسیون توسط مدیر پروژه"""
    __tablename__ = 'commission_requests'
    __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)
    manager_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    
    # مبالغ درخواستی
    requested_amount = db.Column(db.Float, nullable=False)  # مبلغ درخواستی مدیر
    system_commission_percent = db.Column(db.Float, default=10)  # درصد سهم سیستم (ثابت)
    system_commission_amount = db.Column(db.Float, nullable=False)  # مبلغ سهم سیستم
    manager_commission_percent = db.Column(db.Float, default=5)  # درصد سهم مدیر (ثابت)
    manager_commission_amount = db.Column(db.Float, nullable=False)  # مبلغ سهم مدیر
    
    # اطلاعات قرارداد و واریز
    contract_id = db.Column(db.Integer, db.ForeignKey('contracts.id'), nullable=True)
    deposit_id = db.Column(db.Integer, db.ForeignKey('deposits.id'), nullable=True)
    
    # اطلاعات تایید
    approved_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)  # ادمین تایید کننده
    approved_at = db.Column(db.DateTime, nullable=True)
    
    # وضعیت درخواست
    status = db.Column(db.String(20), default='pending')  # pending, approved, rejected, paid
    
    # توضیحات
    description = db.Column(db.Text, nullable=True)
    admin_response = 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)
    
    # شماره پیگیری درخواست
    request_number = db.Column(db.String(20), unique=True, nullable=False)
    
    # ========== روابط ==========
    
    # رابطه با Project
    project = db.relationship(
        'Project',
        foreign_keys=[project_id],
        backref='commission_requests'  # نام یکتا
    )
    
    # رابطه با Manager (User)
    manager = db.relationship(
        'User',
        foreign_keys=[manager_id],
        backref='manager_commission_requests'  # نام یکتا
    )
    
    # رابطه با Admin (User) - تایید کننده
    approver = db.relationship(
        'User',
        foreign_keys=[approved_by],
        backref='approved_commission_requests'  # نام یکتا
    )
    
    # رابطه با Contract
    contract = db.relationship(
        'Contract',
        foreign_keys=[contract_id],
        backref='commission_requests'  # نام یکتا
    )
    
    # رابطه با Deposit
    deposit = db.relationship(
        'Deposit',
        foreign_keys=[deposit_id],
        backref='commission_requests'  # نام یکتا
    )
    
    # ========== متدها ==========
    
    @classmethod
    def generate_request_number(cls):
        """تولید شماره پیگیری یکتا برای درخواست"""
        while True:
            # فرمت: CR-YYYYMMDD-XXXXX
            date_part = datetime.now().strftime('%Y%m%d')
            random_part = ''.join(random.choices(string.digits, k=5))
            request_number = f"CR-{date_part}-{random_part}"
            
            # بررسی یکتا بودن
            existing = cls.query.filter_by(request_number=request_number).first()
            if not existing:
                return request_number
    
    @classmethod
    def create_from_amount(cls, project_id, manager_id, amount, description=None, contract_id=None, deposit_id=None):
        """ایجاد درخواست کمیسیون از روی مبلغ"""
        system_percent = 10
        manager_percent = 5
        
        system_amount = amount * (system_percent / 100)
        manager_amount = amount * (manager_percent / 100)
        
        request = cls(
            project_id=project_id,
            manager_id=manager_id,
            requested_amount=amount,
            system_commission_percent=system_percent,
            system_commission_amount=system_amount,
            manager_commission_percent=manager_percent,
            manager_commission_amount=manager_amount,
            contract_id=contract_id,
            deposit_id=deposit_id,
            description=description,
            status='pending',
            request_number=cls.generate_request_number()
        )
        return request
    
    @classmethod
    def create_from_contract(cls, project_id, manager_id, contract_id, description=None):
        """ایجاد درخواست کمیسیون از روی قرارداد"""
        from app.models import Contract
        contract = Contract.query.get(contract_id)
        if not contract:
            raise ValueError("قرارداد مورد نظر یافت نشد")
        
        # محاسبه مبلغ قابل پرداخت (مبلغ باقیمانده قرارداد)
        amount = contract.remaining_amount
        if amount <= 0:
            raise ValueError("مبلغ باقیمانده قرارداد صفر یا منفی است")
        
        return cls.create_from_amount(
            project_id=project_id,
            manager_id=manager_id,
            amount=amount,
            description=description or f"درخواست کمیسیون برای قرارداد {contract.id}",
            contract_id=contract_id
        )
    
    @classmethod
    def create_from_deposit(cls, project_id, manager_id, deposit_id, description=None):
        """ایجاد درخواست کمیسیون از روی واریز"""
        from app.models import Deposit
        deposit = Deposit.query.get(deposit_id)
        if not deposit:
            raise ValueError("واریز مورد نظر یافت نشد")
        
        # محاسبه مبلغ قابل پرداخت
        amount = deposit.amount
        if amount <= 0:
            raise ValueError("مبلغ واریز صفر یا منفی است")
        
        return cls.create_from_amount(
            project_id=project_id,
            manager_id=manager_id,
            amount=amount,
            description=description or f"درخواست کمیسیون برای واریز {deposit.id}",
            deposit_id=deposit_id
        )
    
    def approve(self, admin_id, response=None):
        """تایید درخواست توسط ادمین"""
        if self.status != 'pending':
            raise ValueError("فقط درخواست‌های در انتظار قابل تایید هستند")
        
        self.status = 'approved'
        self.approved_by = admin_id
        self.approved_at = datetime.utcnow()
        self.admin_response = response or "درخواست تایید شد"
        self.updated_at = datetime.utcnow()
    
    def reject(self, admin_id, response=None):
        """رد درخواست توسط ادمین"""
        if self.status != 'pending':
            raise ValueError("فقط درخواست‌های در انتظار قابل رد هستند")
        
        self.status = 'rejected'
        self.approved_by = admin_id
        self.approved_at = datetime.utcnow()
        self.admin_response = response or "درخواست رد شد"
        self.updated_at = datetime.utcnow()
    
    def mark_as_paid(self):
        """علامت زدن درخواست به عنوان پرداخت شده"""
        if self.status != 'approved':
            raise ValueError("فقط درخواست‌های تایید شده قابل پرداخت هستند")
        
        self.status = 'paid'
        self.updated_at = datetime.utcnow()
    
    def cancel(self, reason=None):
        """لغو درخواست توسط مدیر"""
        if self.status not in ['pending', 'approved']:
            raise ValueError("فقط درخواست‌های در انتظار یا تایید شده قابل لغو هستند")
        
        self.status = 'cancelled'
        self.admin_response = reason or "درخواست لغو شد"
        self.updated_at = datetime.utcnow()
    
    def get_status_display(self):
        """نمایش وضعیت به فارسی"""
        status_map = {
            'pending': 'در انتظار بررسی',
            'approved': 'تایید شده',
            'rejected': 'رد شده',
            'paid': 'پرداخت شده',
            'cancelled': 'لغو شده'
        }
        return status_map.get(self.status, self.status)
    
    def get_requested_amount_formatted(self):
        """دریافت مبلغ درخواستی به صورت فرمت شده"""
        return f"{self.requested_amount:,.0f}"
    
    def get_system_commission_formatted(self):
        """دریافت کمیسیون سیستم به صورت فرمت شده"""
        return f"{self.system_commission_amount:,.0f}"
    
    def get_manager_commission_formatted(self):
        """دریافت کمیسیون مدیر به صورت فرمت شده"""
        return f"{self.manager_commission_amount:,.0f}"
    
    def get_total_commission(self):
        """دریافت مجموع کمیسیون‌ها"""
        return self.system_commission_amount + self.manager_commission_amount
    
    def get_total_commission_formatted(self):
        """دریافت مجموع کمیسیون‌ها به صورت فرمت شده"""
        return f"{self.get_total_commission():,.0f}"
    
    def get_remaining_days(self):
        """دریافت روزهای باقیمانده تا انقضای درخواست (7 روز)"""
        if self.status != 'pending':
            return 0
        
        days_passed = (datetime.utcnow() - self.created_at).days
        remaining = 7 - days_passed
        return max(0, remaining)
    
    def is_expired(self):
        """بررسی انقضای درخواست (بعد از 7 روز)"""
        return self.get_remaining_days() <= 0
    
    def to_dict(self):
        """تبدیل به دیکشنری برای JSON"""
        return {
            'id': self.id,
            'request_number': self.request_number,
            'project_id': self.project_id,
            'project_name': self.project.name if self.project else None,
            'manager_id': self.manager_id,
            'manager_name': self.manager.fullname if self.manager else None,
            'requested_amount': self.requested_amount,
            'requested_amount_formatted': self.get_requested_amount_formatted(),
            'system_commission_percent': self.system_commission_percent,
            'system_commission_amount': self.system_commission_amount,
            'system_commission_formatted': self.get_system_commission_formatted(),
            'manager_commission_percent': self.manager_commission_percent,
            'manager_commission_amount': self.manager_commission_amount,
            'manager_commission_formatted': self.get_manager_commission_formatted(),
            'total_commission': self.get_total_commission(),
            'total_commission_formatted': self.get_total_commission_formatted(),
            'contract_id': self.contract_id,
            'deposit_id': self.deposit_id,
            'status': self.status,
            'status_display': self.get_status_display(),
            'description': self.description,
            'admin_response': self.admin_response,
            'approved_by': self.approved_by,
            'approver_name': self.approver.fullname if self.approver else None,
            'approved_at': self.approved_at.strftime('%Y-%m-%d %H:%M:%S') if self.approved_at else None,
            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
            'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M:%S') if self.updated_at else None,
            'remaining_days': self.get_remaining_days(),
            'is_expired': self.is_expired()
        }
    
    def __repr__(self):
        return f'<CommissionRequest {self.request_number} - {self.status} - {self.requested_amount}>'


# ============================================
# توابع کمکی برای مدیریت کمیسیون
# ============================================

def get_pending_commission_requests(manager_id=None):
    """دریافت درخواست‌های کمیسیون در انتظار"""
    query = CommissionRequest.query.filter_by(status='pending')
    if manager_id:
        query = query.filter_by(manager_id=manager_id)
    return query.order_by(CommissionRequest.created_at.desc()).all()


def get_approved_commission_requests(manager_id=None):
    """دریافت درخواست‌های کمیسیون تایید شده"""
    query = CommissionRequest.query.filter_by(status='approved')
    if manager_id:
        query = query.filter_by(manager_id=manager_id)
    return query.order_by(CommissionRequest.approved_at.desc()).all()


def get_paid_commission_requests(manager_id=None):
    """دریافت درخواست‌های کمیسیون پرداخت شده"""
    query = CommissionRequest.query.filter_by(status='paid')
    if manager_id:
        query = query.filter_by(manager_id=manager_id)
    return query.order_by(CommissionRequest.updated_at.desc()).all()


def get_commission_requests_by_project(project_id):
    """دریافت درخواست‌های کمیسیون یک پروژه"""
    return CommissionRequest.query.filter_by(
        project_id=project_id
    ).order_by(CommissionRequest.created_at.desc()).all()


def get_commission_request_statistics(manager_id=None):
    """دریافت آمار درخواست‌های کمیسیون"""
    query = CommissionRequest.query
    if manager_id:
        query = query.filter_by(manager_id=manager_id)
    
    total = query.count()
    pending = query.filter_by(status='pending').count()
    approved = query.filter_by(status='approved').count()
    rejected = query.filter_by(status='rejected').count()
    paid = query.filter_by(status='paid').count()
    cancelled = query.filter_by(status='cancelled').count()
    
    # مجموع مبالغ
    total_amount = query.with_entities(db.func.sum(CommissionRequest.requested_amount)).scalar() or 0
    pending_amount = query.filter_by(status='pending').with_entities(db.func.sum(CommissionRequest.requested_amount)).scalar() or 0
    approved_amount = query.filter_by(status='approved').with_entities(db.func.sum(CommissionRequest.requested_amount)).scalar() or 0
    paid_amount = query.filter_by(status='paid').with_entities(db.func.sum(CommissionRequest.requested_amount)).scalar() or 0
    
    return {
        'total': total,
        'pending': pending,
        'approved': approved,
        'rejected': rejected,
        'paid': paid,
        'cancelled': cancelled,
        'total_amount': total_amount,
        'pending_amount': pending_amount,
        'approved_amount': approved_amount,
        'paid_amount': paid_amount
    }


def create_commission_from_request(request_id):
    """ایجاد کمیسیون سیستم از روی درخواست تایید شده"""
    from app.models import SystemCommission
    
    request = CommissionRequest.query.get(request_id)
    if not request:
        raise ValueError("درخواست یافت نشد")
    
    if request.status != 'approved':
        raise ValueError("فقط درخواست‌های تایید شده قابل تبدیل به کمیسیون هستند")
    
    # ایجاد کمیسیون سیستم
    commission = SystemCommission.calculate_commissions(
        contract_id=request.contract_id,
        project_id=request.project_id,
        deposit_id=request.deposit_id,
        amount=request.requested_amount,
        manager_id=request.manager_id
    )
    
    # کپی توضیحات
    commission.description = f"ایجاد شده از درخواست {request.request_number}: {request.description}"
    
    # علامت زدن درخواست به عنوان پرداخت شده
    request.mark_as_paid()
    
    return commission