
from odoo import models, fields, api
from datetime import date, timedelta,datetime
import re
import calendar
from odoo.exceptions import UserError


class SOS_Sales_Achievement_Report(models.Model):
    _name = 'sos_sales_achievement_report'
    _description = 'Sosaley Sales Achievement Report'
    _rec_name='financial_year'
    _sql_constraints = [
        ('unique_financial_year_sales_person', 'UNIQUE(financial_year, sales_person)', 'The combination of Financial Year and Sales Person must be unique.')
    ]
    display_name = fields.Char(string="Name", compute='_compute_display_name', store=True)
    financial_year = fields.Char(string="Financial Year", default=lambda self: self._get_financial_year())
    sales_person = fields.Many2one('res.users', string='Sales person',required=True)
    overall_target = fields.Float(string="Overall Target")
    opening_balance = fields.Float(string="Opening Balance")
    planned_target_april = fields.Float(string="Planned For April")
    actual_target_april = fields.Float(string="Actual For April")
    billed_target_april = fields.Float(string="Billed For April")
    yet_to_billed_target_april = fields.Float(string="Yet to Billed For April",compute="_compute_yet_to_billed_april")
    collected_target_april = fields.Float(string="Collected For April")
    achievement_percentage_april = fields.Char(string="Achievement Percentage For April", compute="_compute_achievement_percentage", store=True)
    planned_target_may = fields.Float(string="Planned For May")
    actual_target_may = fields.Float(string="Actual For May")
    billed_target_may = fields.Float(string="Billed For May")
    yet_to_billed_target_may = fields.Float(string="Yet to Billed For May",compute="_compute_yet_to_billed_targets")
    collected_target_may = fields.Float(string="Collected For May")
    achievement_percentage_may = fields.Char(string="Achievement Percentage For May", compute="_compute_achievement_percentage", store=True)
    planned_target_june = fields.Float(string="Planned For June")
    actual_target_june = fields.Float(string="Actual For June")
    billed_target_june = fields.Float(string="Billed For June")
    yet_to_billed_target_june = fields.Float(string="Yet to Billed For June")
    collected_target_june = fields.Float(string="Collected For June")
    achievement_percentage_june = fields.Char(string="Achievement Percentage For June", compute="_compute_achievement_percentage", store=True)
    planned_target_july = fields.Float(string="Planned For July")
    actual_target_july = fields.Float(string="Actual For July")
    billed_target_july = fields.Float(string="Billed For July")
    yet_to_billed_target_july = fields.Float(string="Yet to Billed For July")
    collected_target_july = fields.Float(string="Collected For July")
    achievement_percentage_july = fields.Char(string="Achievement Percentage For July", compute="_compute_achievement_percentage", store=True)
    planned_target_august = fields.Float(string="Planned For August")
    actual_target_august = fields.Float(string="Actual For August")
    billed_target_august = fields.Float(string="Billed For August")
    yet_to_billed_target_august = fields.Float(string="Yet to Billed For August")
    collected_target_august = fields.Float(string="Collected For August")
    achievement_percentage_august = fields.Char(string="Achievement Percentage For August", compute="_compute_achievement_percentage", store=True)
    planned_target_september = fields.Float(string="Planned For September")
    actual_target_september = fields.Float(string="Actual For September")
    billed_target_september = fields.Float(string="Billed For September")
    yet_to_billed_target_september = fields.Float(string="Yet to Billed For September")
    collected_target_september = fields.Float(string="Collected For September")
    achievement_percentage_september = fields.Char(string="Achievement Percentage For September", compute="_compute_achievement_percentage", store=True)
    planned_target_october = fields.Float(string="Planned For October")
    actual_target_october = fields.Float(string="Actual For October")
    billed_target_october = fields.Float(string="Billed For October")
    yet_to_billed_target_october = fields.Float(string="Yet to Billed For October")
    collected_target_october = fields.Float(string="Collected For October")
    achievement_percentage_october = fields.Char(string="Achievement Percentage For October", compute="_compute_achievement_percentage", store=True)
    planned_target_november = fields.Float(string="Planned For November")
    actual_target_november = fields.Float(string="Actual For November")
    billed_target_november = fields.Float(string="Billed For November")
    yet_to_billed_target_november = fields.Float(string="Yet to Billed For November")
    collected_target_november = fields.Float(string="Collected For November")
    achievement_percentage_november = fields.Char(string="Achievement Percentage For November", compute="_compute_achievement_percentage", store=True)
    planned_target_december = fields.Float(string="Planned For December")
    actual_target_december = fields.Float(string="Actual For December")
    billed_target_december = fields.Float(string="Billed For December")
    yet_to_billed_target_december = fields.Float(string="Yet to Billed For December")
    collected_target_december = fields.Float(string="Collected For December")
    achievement_percentage_december = fields.Char(string="Achievement Percentage For December", compute="_compute_achievement_percentage", store=True)
    planned_target_january = fields.Float(string="Planned For January")
    actual_target_january = fields.Float(string="Actual For January")
    billed_target_january = fields.Float(string="Billed For January")
    yet_to_billed_target_january = fields.Float(string="Yet to Billed For January")
    collected_target_january = fields.Float(string="Collected For January")
    achievement_percentage_january = fields.Char(string="Achievement Percentage For January", compute="_compute_achievement_percentage", store=True)
    planned_target_february = fields.Float(string="Planned For February")
    actual_target_february = fields.Float(string="Actual For February")
    billed_target_february = fields.Float(string="Billed For February")
    yet_to_billed_target_february = fields.Float(string="Yet to Billed For February")
    collected_target_february = fields.Float(string="Collected For February")
    achievement_percentage_february = fields.Char(string="Achievement Percentage For February", compute="_compute_achievement_percentage", store=True)
    planned_target_march = fields.Float(string="Planned For March")
    actual_target_march = fields.Float(string="Actual For March")
    billed_target_march = fields.Float(string="Billed For March")
    yet_to_billed_target_march = fields.Float(string="Yet to Billed For March")

    collected_target_march = fields.Float(string="Collected For March")
    achievement_percentage_march = fields.Char(string="Achievement Percentage For March", compute="_compute_achievement_percentage", store=True)
    planned_target_total = fields.Float(string="Planned Total", compute="_compute_planned_total_target", store=True)
    actual_target_total = fields.Float(string="Actual Total", compute="_compute_actual_total_target", store=True)
    achievement_percentage_total = fields.Char(string="Achievement Percentage For Total", compute="_compute_achievement_percentage_total", store=True)
    billed_target_total = fields.Char(string="Billed For Total", compute="_compute_billed_total_target", store=True)
    yet_to_billed_target_total  = fields.Char(string="Billed For Total", compute="_compute_yet_to_billed_total_target", store=True)
    collected_target_total = fields.Float(string="collected For Total", compute="_compute_collected_total_target", store=True)
    can_edit_billed_target = fields.Boolean(
        string="Can Edit Billed Target",
        compute="_compute_can_edit_billed_target",
        store=False,
    )
    ytd_target = fields.Float(string="YTD Total", store=True, compute="_compute_ytd_target")
    ytd_sales = fields.Float(string="YTD Sales", store=True, compute="_compute_ytd_sales_target")
    ytd_sales_percentage = fields.Float(string="YTD Sales Percentage", store=True, compute="_compute_ytd_sales_percentage")
    ytd_yet_to_billed = fields.Float(string="YTD Billed", store=True,compute="_compute_ytd_yet_to_billed")
    ytd_billed = fields.Float(string="YTD Billed", store=True,compute="_compute_ytd_billed")
    ytd_collected = fields.Float(string="YTD Collected", store=True,compute="_compute_ytd_collected")
    line_ids = fields.One2many('sos_sales_achievement_report_brief', 'ref_id',copy=True)
    billing_collection_line_ids = fields.One2many(
            'sos_billing_collection', 
            'ref_id', 
            string="Billing Collection Lines"
        )  
    @api.depends('financial_year', 'sales_person')
    def _compute_display_name(self):
        for record in self:
            record.display_name = f"{record.financial_year or ''} / {record.sales_person.name or ''}"

    @api.depends('opening_balance', 'actual_target_april', 'billed_target_april')
    def _compute_yet_to_billed_april(self):
        for rec in self:
            rec.yet_to_billed_target_april = (rec.opening_balance or 0.0) + \
                                            (rec.actual_target_april or 0.0) - \
                                            (rec.billed_target_april or 0.0)

    @api.depends(
    'yet_to_billed_target_april',  # link to April
    'actual_target_may', 'billed_target_may',
    'actual_target_june', 'billed_target_june',
    'actual_target_july', 'billed_target_july',
    'actual_target_august', 'billed_target_august',
    'actual_target_september', 'billed_target_september',
    'actual_target_october', 'billed_target_october',
    'actual_target_november', 'billed_target_november',
    'actual_target_december', 'billed_target_december',
    'actual_target_january', 'billed_target_january',
    'actual_target_february', 'billed_target_february',
    'actual_target_march', 'billed_target_march',
    )
    def _compute_yet_to_billed_targets(self):
        month_order = [
            'may', 'june', 'july', 'august', 'september',
            'october', 'november', 'december',
            'january', 'february', 'march'
        ]

        for rec in self:
            prev_yet_to_bill = rec.yet_to_billed_target_april or 0.0
            for month in month_order:
                actual = getattr(rec, f'actual_target_{month}', 0.0) or 0.0
                billed = getattr(rec, f'billed_target_{month}', 0.0) or 0.0
                result = prev_yet_to_bill + actual - billed
                setattr(rec, f'yet_to_billed_target_{month}', result)
                prev_yet_to_bill = result



    @api.depends(
            'yet_to_billed_target_april', 'yet_to_billed_target_may', 'yet_to_billed_target_june',
            'yet_to_billed_target_july', 'yet_to_billed_target_august', 'yet_to_billed_target_september',
            'yet_to_billed_target_october', 'yet_to_billed_target_november', 'yet_to_billed_target_december',
            'yet_to_billed_target_january', 'yet_to_billed_target_february', 'yet_to_billed_target_march'
        )
    def _compute_ytd_yet_to_billed(self):
        month_map = [
            'april', 'may', 'june', 'july', 'august', 'september',
            'october', 'november', 'december',
            'january', 'february', 'march'
        ]
        current_month = date.today().month

        # In FY April to March, January=10th index
        if current_month >= 4:
            months_to_include = month_map[:current_month - 4 + 1]
        else:
            months_to_include = month_map[:current_month + 9 + 1]

        for rec in self:
            total = 0.0
            for m in months_to_include:
                total += getattr(rec, f'yet_to_billed_target_{m}', 0.0)
            rec.ytd_yet_to_billed = total
    def action_view_billed_lines(self):
        self.ensure_one()

        month = int(self.env.context.get('month', 4))  # default April
        action = self.env.context.get('action', 'Collected')
        if action == 'Billed':
            view_id = self.env.ref('sos_sales.view_sos_billed_collection_wizard_form_billed').id
        else:
            view_id = self.env.ref('sos_sales.view_sos_billed_collection_wizard_form_collected').id

        # Extract year from financial_year string like 'FY 2025-2026'
        match = re.search(r'FY\s*(\d{4})', self.financial_year or '')
        year = int(match.group(1)) if match else date.today().year

        # Get month date range
        last_day = calendar.monthrange(year, month)[1]
        from_date = date(year, month, 1)
        to_date = date(year, month, last_day)

        # Use the actual related record's value (not the related field)
        sales_person_id = self.sales_person.id or self.ref('sales_person').id

        # If sales_person is still None, raise a warning
        if not sales_person_id:
            raise UserError("Sales person is missing in this record.")

        # Search filtered billing lines
        billed_lines = self.env['sos_billing_collection'].search([
            ('sales_person', '=', sales_person_id),
            ('action_status', '=', action),
            ('date_of_action', '>=', from_date),
            ('date_of_action', '<=', to_date),
        ])
        wizard = self.env['sos_billed_collection_wizard'].create({
            'main_parent_id': self.id,
            'billed_line_ids': [(6, 0, billed_lines.ids)],
            'action_status': action,
        })

        return {
            'name': f"{self.env.context.get('action')} Items",
            'type': 'ir.actions.act_window',
            'res_model': 'sos_billed_collection_wizard',
            'view_mode': 'form',
            'view_id': view_id,
            'target': 'new',
            'res_id': wizard.id,
        }
    
    # def action_view_brief_lines_acc(self):
    #     return {
    #         'name': "Action",
    #         'type': 'ir.actions.act_window',
    #         'res_model': 'sos_sales_achievement_report_brief',
    #         'view_mode': 'form',
    #         'view_id': self.env.ref('sos_sales.view_form_sos_sales_achievement_acc').id,
    #         'target': 'new',
    #         'context': {
    #         'ref_record_id': self.id
    #     }
    #     }
    def action_view_brief_lines_acc(self):
        self.ensure_one()
        domain = [('ref_record_id', '=', self.id)]

       

        brief_lines = self.env['sos_sales_achievement_report_brief'].search(domain)

        return {
            'name': 'Achievement Brief Lines',
            'type': 'ir.actions.act_window',
            'res_model': 'sos_sales_achievement_report_brief_wizard',
            'view_mode': 'form',
            'target': 'new',
            'context': {
                'default_brief_line_ids': [(6, 0, brief_lines.ids)],
                'default_parent_id': self.id,
            }
        }
    def action_view_brief_lines(self):
        self.ensure_one()
        domain = [('ref_id', '=', self.id)]

        # Extract starting year from 'FY 2025-2026'
        match = re.search(r'FY\s*(\d{4})', self.financial_year or '')
        if match:
            year = int(match.group(1))
        else:
            raise ValueError(f"Unable to extract year from financial year: {self.financial_year}")

        month = int(self.env.context.get('month', 0))

        if month:
            # Filter specific month
            domain.append(('action_date', '>=', f'{year}-{month:02d}-01'))
            last_day = calendar.monthrange(year, month)[1]
            domain.append(('action_date', '<=', f'{year}-{month:02d}-{last_day:02d}'))
        else:
            # Filter for entire financial year (April to March)
            start_date = f'{year}-04-01'
            end_date = f'{year + 1}-03-31'
            domain.append(('action_date', '>=', start_date))
            domain.append(('action_date', '<=', end_date))

        brief_lines = self.env['sos_sales_achievement_report_brief'].search(domain)

        return {
            'name': 'Achievement Brief Lines',
            'type': 'ir.actions.act_window',
            'res_model': 'sos_sales_achievement_report_brief_wizard',
            'view_mode': 'form',
            'target': 'new',
            'context': {
                'default_brief_line_ids': [(6, 0, brief_lines.ids)],
                'default_parent_id': self.id,
            }
        }



    @api.depends(
        'collected_target_april', 'collected_target_may', 'collected_target_june',
        'collected_target_july', 'collected_target_august', 'collected_target_september',
        'collected_target_october', 'collected_target_november', 'collected_target_december',
        'collected_target_january', 'collected_target_february', 'collected_target_march'
    )
    def _compute_ytd_collected(self):
        month_map = [
            'april', 'may', 'june', 'july', 'august', 'september',
            'october', 'november', 'december',
            'january', 'february', 'march'
        ]
        current_month = date.today().month

        # In FY April to March, January=10th index
        if current_month >= 4:
            months_to_include = month_map[:current_month - 4 + 1]
        else:
            months_to_include = month_map[:current_month + 9 + 1]

        for rec in self:
            total = 0.0
            for m in months_to_include:
                total += getattr(rec, f'collected_target_{m}', 0.0)
            rec.ytd_collected = total
    @api.depends(
        'billed_target_april', 'billed_target_may', 'billed_target_june',
        'billed_target_july', 'billed_target_august', 'billed_target_september',
        'billed_target_october', 'billed_target_november', 'billed_target_december',
        'billed_target_january', 'billed_target_february', 'billed_target_march'
    )
    def _compute_ytd_billed(self):
        month_map = [
            'april', 'may', 'june', 'july', 'august', 'september',
            'october', 'november', 'december',
            'january', 'february', 'march'
        ]
        current_month = date.today().month

        # In FY April to March, January=10th index
        if current_month >= 4:
            months_to_include = month_map[:current_month - 4 + 1]
        else:
            months_to_include = month_map[:current_month + 9 + 1]

        for rec in self:
            total = 0.0
            for m in months_to_include:
                total += getattr(rec, f'billed_target_{m}', 0.0)
            rec.ytd_billed = total
    @api.depends(
        'achievement_percentage_april', 'achievement_percentage_may', 'achievement_percentage_june',
        'achievement_percentage_july', 'achievement_percentage_august', 'achievement_percentage_september',
        'achievement_percentage_october', 'achievement_percentage_november', 'achievement_percentage_december',
        'achievement_percentage_january', 'achievement_percentage_february', 'achievement_percentage_march',
    )
    def _compute_ytd_sales_percentage(self):
        month_map = [
            'april', 'may', 'june', 'july', 'august', 'september',
            'october', 'november', 'december',
            'january', 'february', 'march'
        ]

        current_month = date.today().month
        if current_month >= 4:
            months_to_include = month_map[:current_month - 4 + 1]
        else:
            months_to_include = month_map[:current_month + 9 + 1]

        for rec in self:
            total = 0.0
            count = 0
            for m in months_to_include:
                raw = getattr(rec, f'achievement_percentage_{m}', '0').replace('%', '').strip()
                try:
                    val = float(raw)
                    total += val
                    count += 1
                except (ValueError, TypeError):
                    continue
            rec.ytd_sales_percentage = round(total / count, 2) if count else 0.0
    @api.depends(
        'actual_target_april', 'actual_target_may', 'actual_target_june',
        'actual_target_july', 'actual_target_august', 'actual_target_september',
        'actual_target_october', 'actual_target_november', 'actual_target_december',
        'actual_target_january', 'actual_target_february', 'actual_target_march'
    )
    def _compute_ytd_sales_target(self):
        month_map = [
            'april', 'may', 'june', 'july', 'august', 'september',
            'october', 'november', 'december',
            'january', 'february', 'march'
        ]
        current_month = date.today().month

        # In FY April to March, January=10th index
        if current_month >= 4:
            months_to_include = month_map[:current_month - 4 + 1]
        else:
            months_to_include = month_map[:current_month + 9 + 1]

        for rec in self:
            total = 0.0
            for m in months_to_include:
                total += getattr(rec, f'actual_target_{m}', 0.0)
            rec.ytd_sales = total
    @api.depends(
        'planned_target_april', 'planned_target_may', 'planned_target_june',
        'planned_target_july', 'planned_target_august', 'planned_target_september',
        'planned_target_october', 'planned_target_november', 'planned_target_december',
        'planned_target_january', 'planned_target_february', 'planned_target_march'
    )
    def _compute_ytd_target(self):
        month_map = [
            'april', 'may', 'june', 'july', 'august', 'september',
            'october', 'november', 'december',
            'january', 'february', 'march'
        ]
        current_month = date.today().month

        # In FY April to March, January=10th index
        if current_month >= 4:
            months_to_include = month_map[:current_month - 4 + 1]
        else:
            months_to_include = month_map[:current_month + 9 + 1]

        for rec in self:
            total = 0.0
            for m in months_to_include:
                total += getattr(rec, f'planned_target_{m}', 0.0)
            rec.ytd_target = total

    @api.depends_context('uid')
    def _compute_can_edit_billed_target(self):
        for record in self:
            record.can_edit_billed_target = (
                self.env.user.has_group('sos_inventory.sos_finance_user') or
                self.env.user.has_group('sos_inventory.sos_management_user')
            )
    @api.depends(
        'collected_target_april','collected_target_may','collected_target_june',
        'collected_target_july','collected_target_august','collected_target_september',
        'collected_target_october','collected_target_november','collected_target_december',
        'collected_target_january','collected_target_february','collected_target_march'
    )
    def _compute_collected_total_target(self):
        for record in self:
            record.collected_target_total = round(sum([
            record.collected_target_april or 0,
            record.collected_target_may or 0,
            record.collected_target_june or 0,
            record.collected_target_july or 0,
            record.collected_target_august or 0,
            record.collected_target_september or 0,
            record.collected_target_october or 0,
            record.collected_target_november or 0,
            record.collected_target_december or 0,
            record.collected_target_january or 0,
            record.collected_target_february or 0,
            record.collected_target_march or 0
        ]), 2)

    @api.depends(
        'billed_target_april','billed_target_may','billed_target_june',
        'billed_target_july','billed_target_august','billed_target_september',
        'billed_target_october','billed_target_november','billed_target_december',
        'billed_target_january','billed_target_february','billed_target_march'
    )
    def _compute_billed_total_target(self):
        for record in self:
            record.billed_target_total = round(sum([
                record.billed_target_april or 0,
                record.billed_target_may or 0,
                record.billed_target_june or 0,
                record.billed_target_july or 0,
                record.billed_target_august or 0,
                record.billed_target_september or 0,
                record.billed_target_october or 0,
                record.billed_target_november or 0,
                record.billed_target_december or 0,
                record.billed_target_january or 0,
                record.billed_target_february or 0,
                record.billed_target_march or 0
            ]), 2)
    @api.depends('actual_target_total', 'planned_target_total')
    def _compute_achievement_percentage_total(self):
        for record in self:
            if record.planned_target_total != 0:
                record.achievement_percentage_total = f"{round((record.actual_target_total / record.planned_target_total) * 100, 2)}%"
            else:
                record.achievement_percentage_total = "0.00%"

    @api.depends(
        'yet_to_billed_target_april','yet_to_billed_target_may','yet_to_billed_target_june',
        'yet_to_billed_target_july','yet_to_billed_target_august','yet_to_billed_target_september',
        'yet_to_billed_target_october','yet_to_billed_target_november','yet_to_billed_target_december',
        'yet_to_billed_target_january','yet_to_billed_target_february','yet_to_billed_target_march'
    )
    def _compute_yet_to_billed_total_target(self):
        for record in self:
            record.yet_to_billed_target_total = round(sum([
                record.yet_to_billed_target_april or 0,
                record.yet_to_billed_target_may or 0,
                record.yet_to_billed_target_june or 0,
                record.yet_to_billed_target_july or 0,
                record.yet_to_billed_target_august or 0,
                record.yet_to_billed_target_september or 0,
                record.yet_to_billed_target_october or 0,
                record.yet_to_billed_target_november or 0,
                record.yet_to_billed_target_december or 0,
                record.yet_to_billed_target_january or 0,
                record.yet_to_billed_target_february or 0,
                record.yet_to_billed_target_march or 0
            ]), 2)
    @api.depends(
        'planned_target_april','planned_target_may','planned_target_june',
        'planned_target_july','planned_target_august','planned_target_september',
        'planned_target_october','planned_target_november','planned_target_december',
        'planned_target_january','planned_target_february','planned_target_march'
    )
    def _compute_planned_total_target(self):
        for record in self:
            record.planned_target_total = sum([
                record.planned_target_april or 0,
                record.planned_target_may or 0,
                record.planned_target_june or 0,
                record.planned_target_july or 0,
                record.planned_target_august or 0,
                record.planned_target_september or 0,
                record.planned_target_october or 0,
                record.planned_target_november or 0,
                record.planned_target_december or 0,
                record.planned_target_january or 0,
                record.planned_target_february or 0,
                record.planned_target_march or 0
            ])
    @api.depends(
        'actual_target_april','actual_target_may','actual_target_june',
        'actual_target_july','actual_target_august','actual_target_september',
        'actual_target_october','actual_target_november','actual_target_december',
        'actual_target_january','actual_target_february','actual_target_march'
    )
    def _compute_actual_total_target(self):
        for record in self:
            record.actual_target_total = sum([
                record.actual_target_april or 0,
                record.actual_target_may or 0,
                record.actual_target_june or 0,
                record.actual_target_july or 0,
                record.actual_target_august or 0,
                record.actual_target_september or 0,
                record.actual_target_october or 0,
                record.actual_target_november or 0,
                record.actual_target_december or 0,
                record.actual_target_january or 0,
                record.actual_target_february or 0,
                record.actual_target_march or 0
            ])
    @api.depends(
        'actual_target_april','actual_target_may','actual_target_june',
        'actual_target_july','actual_target_august','actual_target_september',
        'actual_target_october','actual_target_november','actual_target_december',
        'actual_target_january','actual_target_february','actual_target_march'
    )
    def _compute_achievement_percentage(self):
        # Loop over all months and calculate achievement percentage dynamically
        for record in self:
            for month in ['april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december', 'january', 'february', 'march']:
                planned_field = f"planned_target_{month}"
                actual_field = f"actual_target_{month}"
                achievement_field = f"achievement_percentage_{month}"
                
                planned_value = getattr(record, planned_field)
                actual_value = getattr(record, actual_field)
                if planned_value != 0:
                    percentage = (actual_value / planned_value) * 100
                    setattr(record, achievement_field, f"{percentage:.2f}%")
                else:
                    setattr(record, achievement_field, "0.00%")
    def _get_financial_year(self):
        current_date = date.today()
        start_year = current_date.year if current_date.month >= 4 else current_date.year - 1
        end_year = start_year + 1
        return f"FY {start_year}-{end_year}"
    def action_report_achievement_btn(self):
        try:
            action = self.env.ref("sos_sales.action_report_achievement").with_context(landscape=True).report_action(self)
            return action
        except ValueError as e:
            print(f"Failed to find report action: {e}")

class SOS_Sales_Achievement_Report_Brief(models.Model):
    _name = 'sos_sales_achievement_report_brief'
    _description = 'Achievement Brief'
    _order = 'action_date desc' 
    def get_financial_year_selection(self):
        current_date = date.today()
        start_year = 2024  # starting from FY 2024-2025
        current_year = current_date.year if current_date.month >= 4 else current_date.year - 1
        end_year = current_year + 1

        selection = []
        for y in range(start_year, current_year + 1):
            fy = f"FY {y}-{y+1}"
            selection.append((fy, fy))
        return selection
    ref_id = fields.Many2one('sos_sales_achievement_report', string="Financial Year", ondelete="cascade")
    ref_record_id = fields.Integer(string="Reference")
    customer_name = fields.Many2one('sos_customers',string="Customer Name", required=True)
    action_date = fields.Date(string="PO Date")
    currency_id = fields.Many2one(
    'res.currency',
    string='Currency',
    default=lambda self: self.env['res.currency'].search([('name', '=', 'INR')], limit=1).id or False
    )
    financial_year = fields.Selection(
    selection=get_financial_year_selection,
    string="Financial Year",
    required=True
)
    sales_person = fields.Many2one('res.users', string='Sales person',related="ref_id.sales_person",store=True)
    po_no  = fields.Char(string="PO No")
    invoice_no  = fields.Char(string="Invoice No")
    proposal_value = fields.Monetary(currency_field='currency_id',string="PO Value(In Lakhs)")
    billed_date = fields.Date(string="Billed Date")
    billed_amount = fields.Monetary(currency_field='currency_id',string="Billed Value(In Lakhs)")
    # def view_lines_acc(self):
    #     self.ensure_one()
    #     return {
    #         'name': 'Achievement Brief Lines',
    #         'type': 'ir.actions.act_window',
    #         'res_model': 'sos_sales_achievement_report_brief',
    #         'view_mode': 'tree',
    #         'domain': [('ref_record_id', '=', self.id)],
    #         'context': {
    #             'default_ref_record_id': self.id
    #         },
    #         'target': 'current',
    #     }
    def delete_achievement_line(self):
        self.unlink()
    def unlink(self):
        for record in self:
            report = self.env['sos_sales_achievement_report'].browse(record.ref_id.id)
            if report and hasattr(report, 'opening_balance'):
                report.write({'opening_balance': report.opening_balance - record.proposal_value})
        return super(SOS_Sales_Achievement_Report_Brief, self).unlink()

    def open_line_form(self):
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window',
            'name': 'Edit Line',
            'res_model': self._name,
            'res_id': self.id,
            'view_mode': 'form',
            'target': 'new',  # Opens as a popup
        }
    def _get_financial_year(self,current_date):
        start_year = current_date.year if current_date.month >= 4 else current_date.year - 1
        end_year = start_year + 1
        return f"FY {start_year}-{end_year}"

    def write(self, vals):
        for rec in self:
            # Previous values
            old_billed_date = rec.billed_date
            old_billed_amount = rec.billed_amount
            report = rec.ref_id
            # New values
            new_billed_date = vals.get('billed_date', old_billed_date)
            new_billed_amount = vals.get('billed_amount', old_billed_amount)
            if isinstance(new_billed_date, str):
                new_billed_date = datetime.strptime(new_billed_date, '%Y-%m-%d').date()

            # Adjust billed target
            if report and old_billed_date and new_billed_date:
                old_month_billed = old_billed_date.strftime('%B').lower()
                new_month_billed = new_billed_date.strftime('%B').lower()
                if old_month_billed != new_month_billed or old_billed_amount != new_billed_amount:
                    old_field_billed = f"billed_target_{old_month_billed}"
                    new_field_billed = f"billed_target_{new_month_billed}"
                    if hasattr(report, old_field_billed):
                        report.write({
                            old_field_billed: max((getattr(report, old_field_billed, 0.0) or 0.0) - old_billed_amount, 0.0)
                        })
                    if hasattr(report, new_field_billed):
                        report.write({
                            new_field_billed: (getattr(report, new_field_billed, 0.0) or 0.0) + new_billed_amount
                        })
                    # Optionally create billing collection entry (if needed
            domain = [
                ('ref_id', '=', report.id),
                ('sales_person', '=', report.sales_person.id),
                ('customer_name', '=', vals.get('customer_name', rec.customer_name.id))
            ]

            existing = self.env['sos_billing_collection'].search(domain, limit=1)

            if not existing:
                self.env['sos_billing_collection'].create({
                    'ref_id': report.id,
                    'customer_name': vals.get('customer_name', rec.customer_name.id),
                    'sales_person': report.sales_person.id,
                    'action_status': 'Billed',
                    'date_of_action': new_billed_date,
                    'po_no':vals.get('po_no'),
                    'value': new_billed_amount
                })
            else:
                existing.write({
                        'value': new_billed_amount, 
                        'po_no':vals.get('po_no'),
                        'date_of_action': new_billed_date
                })

        return super(SOS_Sales_Achievement_Report_Brief, self).write(vals)

    @api.model
    def create(self, vals):
        ref_id = vals.get('ref_id')
        vals['ref_record_id'] = ref_id

        action_date = vals.get('action_date')
        billed_date = vals.get('billed_date')
        customer_name = vals.get('customer_name')
        value = vals.get('proposal_value', 0.0)
        billed_value = vals.get('billed_amount', 0.0)
        ref_id = vals.get('ref_id')

        if isinstance(action_date, str):
            action_date = datetime.strptime(action_date, '%Y-%m-%d').date()
        if isinstance(billed_date, str):
            billed_date = datetime.strptime(billed_date, '%Y-%m-%d').date()

        if ref_id and action_date:
            report = self.env['sos_sales_achievement_report'].browse(ref_id)
            month_name = action_date.strftime('%B').lower()
            actual_field = f"actual_target_{month_name}"
            current_date = date.today()
            start_year = current_date.year if current_date.month >= 4 else current_date.year - 1
            end_year = start_year + 1
            current_fy = f"FY {start_year}-{end_year}"
            if vals.get('financial_year') != current_fy:
                report.write({'opening_balance': report.opening_balance + value})

            
            if vals.get('financial_year') == current_fy:
                if hasattr(report, actual_field):
                    current_val = getattr(report, actual_field) or 0.0
                    report.write({actual_field: current_val + value})

            if billed_date:
                self.env['sos_billing_collection'].create({
                    'ref_id': report.id,
                    'customer_name': customer_name,
                    'sales_person': report.sales_person.id,
                    'action_status': 'Billed',
                    'date_of_action': billed_date,
                    'value': billed_value,
                    'po_no':vals.get('po_no')
                })
        new_record = super(SOS_Sales_Achievement_Report_Brief, self).create(vals)
        return new_record


class SOS_Sales_Achievement_Report_Brief_Wizard(models.TransientModel):
    _name = 'sos_sales_achievement_report_brief_wizard'
    _description = 'Achievement Brief Wizard'
    

    parent_id = fields.Many2one('sos_sales_achievement_report', string="Sales Achievement Report")
    brief_line_ids = fields.Many2many(
        'sos_sales_achievement_report_brief',
        relation='sos_brief_wizard_rel',  # Custom table name
        string="Brief Lines",
        readonly=True
    )
    

    def action_add_new_brief_line(self):
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window',
            'name': 'Add Brief Line',
            'res_model': 'sos_sales_achievement_report_brief',
            'view_mode': 'form',
            'target': 'new',
            'context': {
                'default_ref_id': self.parent_id.id,
                'default_currency_id': self.env.ref('base.INR').id,
            }
        }
class SosBilledCollectionWizard(models.TransientModel):
    _name = 'sos_billed_collection_wizard'
    _description = 'Billed Collection Lines Wizard'

    main_parent_id = fields.Many2one('sos_sales_achievement_report', string="Sales Achievement Report")
    billed_line_ids = fields.Many2many(
        'sos_billing_collection',
        string="Billed Lines",
        readonly=True,
        domain="[('ref_id', '=', main_parent_id)]"
    )
    action_status = fields.Selection([
        ('Billed', 'Billed'),
        ('Collected', 'Collected')
    ], string='Action Status', readonly=True)
    @api.model
    def default_get(self, fields_list):
        res = super(SosBilledCollectionWizard, self).default_get(fields_list)
        main_parent_id = self.env.context.get('active_id')
        if main_parent_id and self.env.context.get('active_model') == 'sos_sales_achievement_report':
            res['main_parent_id'] = main_parent_id
            # Populate billed_line_ids with related sos_billing_collection records
            billing_lines = self.env['sos_billing_collection'].search([('ref_id', '=', main_parent_id)])
            res['billed_line_ids'] = [(6, 0, billing_lines.ids)]
        return res

    def action_add_new_collection_line(self):
        self.ensure_one()
        if not self.main_parent_id:
            raise UserError("No Sales Achievement Report found.")
        if self.action_status == "Collected":
            form_title="Collection"
            view_xml_id="view_sos_billing_collection_minimal_form_collection"
        else:
            form_title="Billed"
            view_xml_id="view_sos_billing_collection_minimal_form_billed"
        return {
            'type': 'ir.actions.act_window',
            'name': f'Add {form_title}',
            'res_model': 'sos_billing_collection',
            'view_mode': 'form',
            'view_id': self.env.ref(f'sos_sales.{view_xml_id}').id,

            'target': 'new',
            'context': {
                'default_ref_id': self.main_parent_id.id,
                'default_action_status': self.action_status,
                'default_sales_person': self.main_parent_id.sales_person.id if self.main_parent_id.sales_person else False,
            }
        }
class SosBillingCollection(models.Model):
    _name = 'sos_billing_collection'
    _description = 'Billing & Collection Details'

    ref_id = fields.Many2one('sos_sales_achievement_report', ondelete="cascade", required=True)
    customer_name = fields.Many2one('sos_customers', string="Customer Name")
    sales_person = fields.Many2one(
        'res.users', 
        string='Sales Executive',
        related="ref_id.sales_person",
        store=True
    )
    action_status = fields.Selection([
        ('Billed', 'Billed'),
        ('Collected', 'Collected')
    ], string='Action')
    date_of_action = fields.Date(string="Date")
    currency_id = fields.Many2one(
        'res.currency',
        string='Currency',
        default=lambda self: self.env['res.currency'].search([('name', '=', 'INR')], limit=1).id or False
    )
    value = fields.Monetary(currency_field='currency_id', string="Value (In Lakhs)")
    customer_name = fields.Many2one('sos_customers',string="Customer Name")
    po_no  = fields.Char(string="PO No")
    invoice_no = fields.Char(string="Invoice No")
    products = fields.Selection(
            [
               ('BHMS 1.2V', 'BHMS 1.2V'), 
                ('BHMS 2V', 'BHMS 2V'), 
                ('BHMS 12V', 'BHMS 12V'),  
                ('BHMS 48V', 'BHMS 48V'),
                ('BMS-HV', 'BMS-HV'),
                ('BMS-LV 100A', 'BMS-LV 100A'), 
                ('BMS-LV 40A', 'BMS-LV 40A'), 
                ('SBMS 55A', 'SBMS 55A'),              
                ('MC 250W', 'MC 250W'),                                
                ('HeartTarang', 'HeartTarang')                  
            ],
            string="Products")
    quantity = fields.Integer(string="Quantity")
    def _get_financial_year(self, current_date):
        start_year = current_date.year if current_date.month >= 4 else current_date.year - 1
        end_year = start_year + 1
        return f"FY {start_year}-{end_year}"
    def delete_form_line(self):
        self.unlink()

    def unlink(self):
        for record in self:

            if record.date_of_action:
                fy = self._get_financial_year(record.date_of_action)
                month_name = record.date_of_action.strftime('%B').lower()
            else:
                fy = False
                month_name = False

            if fy and month_name:
                actual_field_name = f"{record.action_status.lower()}_target_{month_name}"

                # Fetch related record where field update should happen (example logic)
                report = self.env['sos_sales_achievement_report'].search([
                    ('financial_year', '=', fy),
                    ('sales_person', '=', record.sales_person.id)
                ], limit=1)

                if report and hasattr(report, actual_field_name):
                    current_val = getattr(report, actual_field_name, 0.0)
                    setattr(report, actual_field_name, current_val - record.value)

        return super(SosBillingCollection, self).unlink()

    @api.model
    def create(self, vals):
        if not vals.get('ref_id'):
            raise UserError("Cannot create record without a valid Sales Achievement Report.")
        
        action_date = vals.get('date_of_action')
        action_status = vals.get('action_status').lower()
        if isinstance(action_date, str):
            action_date = datetime.strptime(action_date, '%Y-%m-%d').date()

        fy = self._get_financial_year(action_date) if action_date else False
        month_name = action_date.strftime('%B').lower() if action_date else False
        final_value = vals.get('value', 0.0)
        actual_field = f"{action_status}_target_{month_name}" if month_name else False

        record = super(SosBillingCollection, self).create(vals)

        # Update the related sos_sales_achievement_report by adding value
        if vals.get('ref_id') and month_name:
            report = self.env['sos_sales_achievement_report'].search([
                ('id', '=', vals.get('ref_id')),
                ('financial_year', '=', fy),
            ])
            if report and hasattr(report, actual_field):
                current_value = getattr(report, actual_field, 0.0) or 0.0
                new_value = current_value + final_value
                report.write({actual_field: new_value})

        return record

