from odoo import api, fields, models, _
from odoo.exceptions import UserError
from dateutil.relativedelta import relativedelta


class LoanManagement(models.Model):
    _name = "loan.management"
    _description = "Loan"
    _order = "id desc"
    _rec_name = "name"
    _inherit = ['mail.thread', 'mail.activity.mixin']


    name = fields.Char(string='Name',tracking=True)
    reference = fields.Char(tracking=True,string='Reference')
    partner_id = fields.Many2one(
        'res.partner',
        string='Customer',
        required=True,
        ondelete='cascade',tracking=True
    )
    loan_amount = fields.Integer(
        string='Loan Amount',
        digits=(16, 2),
        required=True,
        tracking=True
    )

    interest_rate = fields.Float(
        string='Interest %',
        digits=(5, 2), 
        required=True,
        tracking=True
    )

    # loan_month = fields.Integer(
    #     string='Duration (months)',
    #     help='Number of months for the loan duration',
    #     required=True,
    #     tracking=True
    # )
    duration_from = fields.Date(string='Start Date',required=True,tracking=True)
    duration_to = fields.Date(string='End Date',required=True,tracking=True)

    deposit_item_ids = fields.One2many(
        'loan.deposit.item',
        'loan_id',
        string='Deposit / Collateral Items',
        tracking=True
    )
    loan_stage = fields.Selection(
        [
            ('draft', 'Draft'),
            ('inprogress', 'In Progress'),
            ('done', 'Done'),
        ],
        default='draft',
        string='Status',
    )
    credit_data_ids = fields.One2many(
        'loan.credit',
        'loan_id',
        string='Credit Data'
    )
    customer_monthly_interest_ids = fields.One2many(
        'loan.monthly.interest',     
        'loan_id',             
        string="Customer Monthly Interests",
        
    )
    remaining_capital = fields.Float(
        string="Remaining Capital",
        compute="_compute_remaining_capital",
        store=True
    )
    remaining_interest = fields.Float(
        string="Remaining Interest",
        compute="_compute_remaining_interest"
    )
    loan_type = fields.Selection(
        [
            ('credit', 'Credit'),
            ('debit', 'Debit'),
        ],string="Loan Type"
    )



    # _sql_constraints = [
    #     (
    #         'loan_amount_positive',
    #         'CHECK(loan_amount IS NOT NULL AND loan_amount > 0)',
    #         'Loan amount must be greater than zero.'
    #     ),
    #     (
    #         'interest_rate_positive',
    #         'CHECK(interest_rate IS NOT NULL AND interest_rate > 0)',
    #         'Interest rate must be greater than zero.'
    #     ),
    #     (
    #         'loan_month_positive',
    #         'CHECK(loan_month IS NOT NULL AND loan_month > 0)',
    #         'Loan duration (months) must be greater than zero.'
    #     ),
    # ]

    @api.model
    def create(self, vals_list):
        for vals in vals_list:
            if vals.get('loan_amount', 0) <= 0:
                raise UserError(_("Loan amount must be greater than zero."))

            if vals.get('interest_rate', 0) <= 0:
                raise UserError(_("Interest rate must be greater than zero."))

            # if vals.get('loan_month', 0) <= 0:
            #     raise UserError(_("Loan duration (months) must be greater than zero."))

        return super().create(vals_list)


    def write(self, vals):
        for rec in self:
            loan_amount = vals.get('loan_amount', rec.loan_amount)
            interest_rate = vals.get('interest_rate', rec.interest_rate)
            # loan_month = vals.get('loan_month', rec.loan_month)

            if loan_amount <= 0:
                raise UserError(_("Loan amount must be greater than zero."))

            if interest_rate <= 0:
                raise UserError(_("Interest rate must be greater than zero."))

            # if loan_month <= 0:
            #     raise UserError(_("Loan duration (months) must be greater than zero."))

        return super().write(vals)

    
#Set last date accourding to loan months
    # @api.onchange('loan_month')
    # def _onchange_loan_month_set_duration(self):
    #     for rec in self:
    #         if rec.loan_month and rec.loan_month > 0:
    #             start = rec.duration_from or fields.Date.today(self.env)
    #             try:
    #                 # Use relativedelta for month arithmetic
    #                 end_date = fields.Date.to_string(
    #                     fields.Date.from_string(start) + relativedelta(months=rec.loan_month)
    #                 )
    #                 rec.duration_from = start
    #                 rec.duration_to = end_date
    #             except Exception:
    #                 # fallback: set only duration_from
    #                 rec.duration_from = start

    def action_confirm(self):
        for rec in self:
            if rec.loan_stage != 'draft':
                continue
            rec.loan_stage = 'inprogress'
        return True


        

    def action_set_done(self):
    
        for loan in self:
            if loan:    
                if self.remaining_capital > 0 or self.remaining_interest > 0:
                    raise UserError(
                        _("%s has %s capital and %s interest remaining.")
                        % (loan.partner_id.name, loan.remaining_capital, self.remaining_interest)
                    )

            loan.loan_stage = "done"




    @api.depends('duration_from', 'loan_month')
    def _compute_duration_to(self):
        for rec in self:
            if rec.duration_from and rec.loan_month:
                rec.duration_to = rec.duration_from + relativedelta(months=rec.loan_month)
            else:
                rec.duration_to = False

# reffernce add ho raha he
    @api.onchange('partner_id','loan_amount')
    def onchange_show_reference_of_loan(self):
        for rec in self:
            if rec.partner_id and rec.loan_amount:
                rec.name = f"{rec.partner_id.name}'s loan amount {rec.loan_amount}"

# remainig amount show kar raha he
    @api.depends('credit_data_ids.credit_amount')
    def _compute_remaining_capital(self):
        for loan in self:
            paid_capital = sum(
                loan.credit_data_ids.filtered(
                    lambda c: c.credit_type in ('capital', 'mix')
                ).mapped('credit_amount')
            )
            loan.remaining_capital = loan.loan_amount - paid_capital

# remainig interest show kar raha he
    def _compute_remaining_interest(self):
        for loan in self:
            paid_interest = sum(
                loan.credit_data_ids.filtered(
                    lambda c: c.credit_type in ('interest', 'mix')
                ).mapped('interest_amount')
            )
            total_interest = sum(
                loan.customer_monthly_interest_ids.mapped('interest_amount')
            )
            loan.remaining_interest = total_interest - paid_interest

       
# set end date todat button
    def set_end_date_today(self):
        for rec in self:
            rec.duration_to = fields.Date.today()
        return True



    def cron_calculate_monthly_interest(self, is_manual=False):
        today = fields.Date.today()

        loans = self.search([('loan_stage', '=', 'inprogress')])

        for loan in loans:

            if not loan.duration_from or not loan.duration_to:
                continue

            start = loan.duration_from
            end = loan.duration_to


            calc_end = end if is_manual else min(today, end)

            existing_dates = [
                d for d in loan.customer_monthly_interest_ids.mapped('date_to') if d
            ]

            if existing_dates:
                last_date = max(existing_dates)
                current_to = last_date + relativedelta(months=1)
            else:
                current_to = start + relativedelta(months=1)

            while current_to <= calc_end:
                current_from = current_to - relativedelta(months=1)

                monthly_interest = (
                    (loan.remaining_capital or 0.0)
                    * (float(loan.interest_rate or 0.0) / 100.0)
                )

                self.env['loan.monthly.interest'].create({
                    'loan_id': loan.id,
                    'date_from': current_from,
                    'date_to': current_to,
                    'interest_amount': monthly_interest,
                })

                current_to += relativedelta(months=1)

            if is_manual:
                last_from = current_to - relativedelta(months=1)

                if last_from < end:
                    days = (end - last_from).days

                    daily_interest = (
                        (loan.remaining_capital or 0.0)
                        * (float(loan.interest_rate or 0.0) / 100.0)
                    ) / 30.0

                    partial_interest = daily_interest * days

                    self.env['loan.monthly.interest'].create({
                        'loan_id': loan.id,
                        'date_from': last_from,
                        'date_to': end,
                        'interest_amount': round(partial_interest, 2),
                    })

    def action_run_monthly_interest_cron(self):
        self.env['loan.management'].cron_calculate_monthly_interest(is_manual=True)
