# app/models/smart_report.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 json


class SmartReport(db.Model):
    """مدل گزارش هوشمند حضور"""
    __tablename__ = 'smart_reports'
    __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)
    contract_id = db.Column(db.Integer, db.ForeignKey('contracts.id'), nullable=False)
    
    # اطلاعات گزارش
    report_date = db.Column(db.Date, nullable=False)
    attendance_count = db.Column(db.Integer, default=0)
    required_attendance = db.Column(db.Integer, default=0)
    attendance_percentage = db.Column(db.Float, default=0)
    
    # وضعیت هوشمند
    smart_status = db.Column(db.String(20), default='pending')  # positive, negative, pending
    
    # مراحل تایید
    manager_approved = db.Column(db.Boolean, default=False)
    manager_approved_at = db.Column(db.DateTime, nullable=True)
    manager_approved_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
    
    employer_approved = db.Column(db.Boolean, default=False)
    employer_approved_at = db.Column(db.DateTime, nullable=True)
    employer_approved_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
    
    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)
    
    # وضعیت نهایی
    final_status = db.Column(db.String(20), default='pending')  # approved, rejected
    
    # داده‌های تکمیلی
    report_data = db.Column(db.JSON, nullable=True)  # اطلاعات دقیق حضور روزانه
    notes = db.Column(db.Text, nullable=True)
    rejection_reason = 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)
    
    # ========== روابط با نام‌های یکتا ==========
    
    # رابطه با Project
    project = db.relationship(
        'Project',
        foreign_keys=[project_id],
        backref='smart_reports_list'  # نام یکتا
    )
    
    # رابطه با User (Employee)
    employee = db.relationship(
        'User',
        foreign_keys=[employee_id],
        backref='employee_smart_reports_list'  # نام یکتا
    )
    
    # رابطه با Contract
    contract = db.relationship(
        'Contract',
        foreign_keys=[contract_id],
        backref='contract_smart_reports_list'  # نام یکتا
    )
    
    # رابطه با User (Manager Approver)
    manager_approver = db.relationship(
        'User',
        foreign_keys=[manager_approved_by],
        backref='approved_smart_reports_manager'  # نام یکتا
    )
    
    # رابطه با User (Employer Approver)
    employer_approver = db.relationship(
        'User',
        foreign_keys=[employer_approved_by],
        backref='approved_smart_reports_employer'  # نام یکتا
    )
    
    # رابطه با User (Admin Verifier)
    admin_verifier = db.relationship(
        'User',
        foreign_keys=[admin_verified_by],
        backref='verified_smart_reports'  # نام یکتا
    )
    
    # ========== متدها ==========
    
    @classmethod
    def generate_report(cls, project_id, employee_id, contract_id, report_date, attendance_data):
        """تولید گزارش هوشمند"""
        required_attendance = 22  # تعداد روزهای کاری مورد نیاز در ماه
        attendance_count = len(attendance_data)
        attendance_percentage = (attendance_count / required_attendance) * 100
        
        # تعیین وضعیت هوشمند
        if attendance_percentage >= 80:
            smart_status = 'positive'
        else:
            smart_status = 'negative'
        
        report = cls(
            project_id=project_id,
            employee_id=employee_id,
            contract_id=contract_id,
            report_date=report_date,
            attendance_count=attendance_count,
            required_attendance=required_attendance,
            attendance_percentage=attendance_percentage,
            smart_status=smart_status,
            report_data=attendance_data
        )
        return report
    
    def approve_manager(self, user_id):
        """تایید توسط مدیر پروژه"""
        self.manager_approved = True
        self.manager_approved_at = datetime.utcnow()
        self.manager_approved_by = user_id
        self._check_approvals()
    
    def approve_employer(self, user_id):
        """تایید توسط کارفرما"""
        self.employer_approved = True
        self.employer_approved_at = datetime.utcnow()
        self.employer_approved_by = user_id
        self._check_approvals()
    
    def verify_admin(self, user_id):
        """تایید نهایی توسط ادمین"""
        self.admin_verified = True
        self.admin_verified_at = datetime.utcnow()
        self.admin_verified_by = user_id
        self._check_approvals()
    
    def _check_approvals(self):
        """بررسی تاییدات و تعیین وضعیت نهایی"""
        if self.manager_approved and self.employer_approved and self.admin_verified:
            if self.smart_status == 'positive':
                self.final_status = 'approved'
            else:
                self.final_status = 'rejected'
                self.rejection_reason = 'گزارش هوشمند منفی است'
    
    def reject(self, user_id, reason=None):
        """رد گزارش"""
        self.final_status = 'rejected'
        if reason:
            self.rejection_reason = reason
    
    def get_status_display(self):
        """نمایش وضعیت هوشمند به فارسی"""
        status_map = {
            'positive': 'مثبت',
            'negative': 'منفی',
            'pending': 'در انتظار'
        }
        return status_map.get(self.smart_status, self.smart_status)
    
    def get_final_status_display(self):
        """نمایش وضعیت نهایی به فارسی"""
        status_map = {
            'pending': 'در انتظار',
            'approved': 'تایید شده',
            'rejected': 'رد شده'
        }
        return status_map.get(self.final_status, self.final_status)
    
    def get_approval_status(self):
        """دریافت وضعیت تاییدات"""
        return {
            'manager': self.manager_approved,
            'employer': self.employer_approved,
            'admin': self.admin_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,
            'employee_id': self.employee_id,
            'employee_name': self.employee.fullname if self.employee else None,
            'contract_id': self.contract_id,
            'report_date': self.report_date.strftime('%Y-%m-%d'),
            'attendance_count': self.attendance_count,
            'required_attendance': self.required_attendance,
            'attendance_percentage': self.attendance_percentage,
            'smart_status': self.smart_status,
            'smart_status_display': self.get_status_display(),
            'final_status': self.final_status,
            'final_status_display': self.get_final_status_display(),
            'approval_status': self.get_approval_status(),
            'manager_approved': self.manager_approved,
            'employer_approved': self.employer_approved,
            'admin_verified': self.admin_verified,
            'notes': self.notes,
            'rejection_reason': self.rejection_reason,
            'report_data': self.report_data,
            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S')
        }
    
    def __repr__(self):
        return f'<SmartReport {self.id} - {self.smart_status} - {self.final_status}>'


class EscrowReport(db.Model):
    """مدل گزارش‌های خلاصه صندوق امانی"""
    __tablename__ = 'escrow_reports'
    __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)
    
    # دوره گزارش
    report_date = db.Column(db.Date, nullable=False)
    report_type = db.Column(db.String(20), default='monthly')  # daily, weekly, monthly, yearly
    period_start = db.Column(db.Date, nullable=True)
    period_end = db.Column(db.Date, nullable=True)
    
    # خلاصه مالی
    opening_balance = db.Column(db.Float, default=0)
    closing_balance = db.Column(db.Float, default=0)
    total_deposits = db.Column(db.Float, default=0)
    total_withdrawals = db.Column(db.Float, default=0)
    total_fees = db.Column(db.Float, default=0)
    transaction_count = db.Column(db.Integer, default=0)
    
    # آمار
    deposit_count = db.Column(db.Integer, default=0)
    withdrawal_count = db.Column(db.Integer, default=0)
    fee_count = db.Column(db.Integer, default=0)
    
    # JSON با جزئیات
    details = db.Column(db.JSON, nullable=True)
    
    # زمان
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # ========== روابط با نام‌های یکتا ==========
    
    # رابطه با EscrowAccount
    escrow = db.relationship(
        'EscrowAccount',
        foreign_keys=[escrow_id],
        backref='escrow_reports_list'  # نام یکتا
    )
    
    # ========== متدها ==========
    
    @classmethod
    def generate_monthly_report(cls, escrow_id, year, month):
        """تولید گزارش ماهانه"""
        from calendar import monthrange
        start_date = datetime(year, month, 1).date()
        end_date = datetime(year, month, monthrange(year, month)[1]).date()
        
        # محاسبه موجودی افتتاحیه
        opening_balance = 0  # محاسبه از تراکنش‌های قبل از شروع ماه
        
        # دریافت تراکنش‌های ماه
        transactions = EscrowTransaction.query.filter(
            EscrowTransaction.escrow_id == escrow_id,
            EscrowTransaction.created_at >= start_date,
            EscrowTransaction.created_at <= end_date,
            EscrowTransaction.status == 'completed'
        ).all()
        
        total_deposits = sum(t.amount for t in transactions if t.transaction_type == 'deposit')
        total_withdrawals = sum(t.amount for t in transactions if t.transaction_type == 'withdraw')
        total_fees = sum(t.amount for t in transactions if t.transaction_type == 'fee')
        
        closing_balance = opening_balance + total_deposits - total_withdrawals - total_fees
        
        report = cls(
            escrow_id=escrow_id,
            report_date=datetime.now().date(),
            report_type='monthly',
            period_start=start_date,
            period_end=end_date,
            opening_balance=opening_balance,
            closing_balance=closing_balance,
            total_deposits=total_deposits,
            total_withdrawals=total_withdrawals,
            total_fees=total_fees,
            transaction_count=len(transactions),
            deposit_count=sum(1 for t in transactions if t.transaction_type == 'deposit'),
            withdrawal_count=sum(1 for t in transactions if t.transaction_type == 'withdraw'),
            fee_count=sum(1 for t in transactions if t.transaction_type == 'fee'),
            details={
                'transactions': [t.to_dict() for t in transactions]
            }
        )
        return report
    
    def get_type_display(self):
        """نمایش نوع گزارش به فارسی"""
        type_map = {
            'daily': 'روزانه',
            'weekly': 'هفتگی',
            'monthly': 'ماهانه',
            'yearly': 'سالانه'
        }
        return type_map.get(self.report_type, self.report_type)
    
    def to_dict(self):
        """تبدیل به دیکشنری برای JSON"""
        return {
            'id': self.id,
            'escrow_id': self.escrow_id,
            'project_name': self.escrow.project.name if self.escrow and self.escrow.project else None,
            'report_date': self.report_date.strftime('%Y-%m-%d'),
            'report_type': self.report_type,
            'report_type_display': self.get_type_display(),
            'period_start': self.period_start.strftime('%Y-%m-%d') if self.period_start else None,
            'period_end': self.period_end.strftime('%Y-%m-%d') if self.period_end else None,
            'opening_balance': self.opening_balance,
            'opening_balance_formatted': f"{self.opening_balance:,.0f}",
            'closing_balance': self.closing_balance,
            'closing_balance_formatted': f"{self.closing_balance:,.0f}",
            'total_deposits': self.total_deposits,
            'total_deposits_formatted': f"{self.total_deposits:,.0f}",
            'total_withdrawals': self.total_withdrawals,
            'total_withdrawals_formatted': f"{self.total_withdrawals:,.0f}",
            'total_fees': self.total_fees,
            'total_fees_formatted': f"{self.total_fees:,.0f}",
            'transaction_count': self.transaction_count,
            'deposit_count': self.deposit_count,
            'withdrawal_count': self.withdrawal_count,
            'fee_count': self.fee_count,
            'details': self.details,
            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S')
        }
    
    def __repr__(self):
        return f'<EscrowReport {self.report_date} - {self.report_type} - Balance:{self.closing_balance}>'