from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
from odoo.exceptions import UserError, ValidationError



class PaProgramLevel(models.Model):
    _name = 'pa.program.level'
    _description = 'Program Levels Screen'
    _rec_name = 'name'
    _order = 'code'

    code = fields.Char(
        string='Level Code',
        required=True,
        copy=False,
        readonly=True,
        index=True,
        default=lambda self: self.env['ir.sequence'].next_by_code('pa.program.level') or _('New'),
    )

    name = fields.Char(
        string='Level Name',
        required=True,
        default=lambda self: _('Technical Tracks'),
        help='Enter the level name such as: cultural, cognitive, religious, developmental, preventive, therapeutic',
    )

    type = fields.Selection([
        ('route', 'Tracks'),
        ('activity', 'Activities'),
        ('medad', 'Medad'),
    ], string='Level Type', required=True, help='Select the type of level')

    description = fields.Text(string='Level Description')

    active = fields.Boolean(string='Level Status', default=True)

    track_ids = fields.One2many(
        'pa.program.track',
        'level_id',
        string='Associated Tracks',
        help='Tracks that belong to this level',
    )


    # Optional: enforce unique code at Python level
    @api.model
    def create(self, vals):
        if 'code' in vals:
            existing = self.search([('code', '=', vals['code'])])
            if existing:
                raise ValidationError(_('كود المستوى يجب أن يكون فريدًا'))
        return super(PaProgramLevel, self).create(vals)

class PaProgramTrack(models.Model):
    _name = 'pa.program.track'
    _description = 'Program Track Screen'
    _rec_name = 'name'
    _order = 'code'

    code = fields.Char(
        string='Track Code',
        required=True,
        copy=False,
        readonly=True,
        index=True,
        default=lambda self: self.env['ir.sequence'].next_by_code('pa.program.track') or _('New'),
    )
    name = fields.Char(string='Track Name', required=True)
    description = fields.Text(string='Track Description')

    # branch = fields.Many2one('age.category',string='Branch')
    branch = fields.Many2one("branch.settings", string='Branch', domain="[('branch_type','=','branches')]")


    gender = fields.Selection(
        [('male', 'Male'), ('female', 'Female')],
        string='Gender',
    )

    age_category = fields.Many2one(
        'age.category',
        string='Age Category',
        help='Filter track based on age category',
    )

    study_category = fields.Many2one('education.level',string='Study Category')
    hobby = fields.Char(string='Hobby')
    study_status = fields.Char(string='Study Status')
    health_status = fields.Char(string='Health Status')
    education_status = fields.Char(string='Educational Status')

    partner_id = fields.Many2one(
        'res.partner',
        string='Associated Partner',
        help='The partner linked to the track'
    )

    active = fields.Boolean(string='Track Status', default=True)

    level_id = fields.Many2one(
        'pa.program.level',
        string='Associated Level',
        required=True,
        ondelete='cascade'
    )



class PaProgram(models.Model):

    _name = 'pa.program'
    _description = 'Programs Screen'
    _rec_name = 'name'
    _order = 'code'

    code = fields.Char(
        string='Program Code',
        required=True,
        copy=False,
        readonly=True,
        index=True,
        default=lambda self: self.env['ir.sequence'].next_by_code('pa.program') or _('New'),
    )

    name = fields.Char(string='Program Name', required=True)

    program_type_id = fields.Many2one(
        'pa.program.type',
        string='Program Type',

    )

    payment_type = fields.Selection([
        ('paid', 'Paid'),
        ('unpaid', 'Unpaid')
    ], string='Payment Type', required=True)

    sponsor_id = fields.Many2one('takaful.sponsorship', string='Linked Sponsor',
                                 help='Sponsor is shown only if the payment type is Paid'
                                 )

    sponsor_support_amount = fields.Float(
        string='Allocated Support Amount',
        related='sponsor_id.total_sponsorship_amount',
        readonly=True,
        help='Support amount as per sponsor details'
    )

    budget = fields.Float(
        string='Program Budget',
        help='Used when payment type = Unpaid'
    )

    location = fields.Selection([
        ('inside', 'Internal'),
        ('outside', 'External')
    ], string='Program Location', required=True)

    description = fields.Text(string='Program Description')

    track_id = fields.Many2one(
        'pa.program.track',
        string='Associated Track',
        help='Each program is linked to one track that contains several activities'
    )

    analytic_account_id = fields.Many2one(
        'account.analytic.account',
        string='Linked Analytic Account',
        readonly=True,
        help='Automatically created analytic account with the same name as the program and cannot be deleted'
    )

    estimated_budget = fields.Float(
        string='Associated Estimated Budget',
        help='Estimated budget related to the analytic account'
    )

    active = fields.Boolean(string='Program Status', default=True)

    # @api.constrains('name')
    # def _create_program_account(self):
    #     for rec in self:
    #         if not rec.name:
    #             continue
    #         # check if analytic account already exists
    #         analytic = self.env["account.analytic.account"].search([("name", "=", rec.name)], limit=1)
    #         if not analytic:
    #             self.env["account.analytic.account"].create({
    #                 "name": rec.name,
    #             })


    @api.constrains('payment_type', 'sponsor_id')
    def _check_sponsor_if_paid(self):
        for record in self:
            if record.payment_type == 'paid' and not record.sponsor_id:
                raise ValidationError(_('يجب اختيار الكافل في حالة نوع الدفع مدفوع'))
            if record.payment_type == 'unpaid' and record.sponsor_id:
                raise ValidationError(_('لا يجب اختيار كافل في حالة نوع الدفع غير مدفوع'))

    @api.model
    def create(self, vals):
        res = super().create(vals)  # ✅ fix
        if not res.analytic_account_id:
            account = self.env['account.analytic.account'].create({
                'name': res.name,
                'active': True,
            })
            res.analytic_account_id = account.id
        return res

    def write(self, vals):
        res = super().write(vals)  # ✅ same correction here
        for record in self:
            if not record.analytic_account_id:
                account = self.env['account.analytic.account'].create({
                    'name': record.name,
                    'active': True,
                })
                record.analytic_account_id = account.id
        return res

class PaProgramActivity(models.Model):
    _name = 'pa.program.activity'
    _description = 'Program Activity'
    _rec_name = 'name'

    code = fields.Char("Activity Code", required=True, copy=False, default=lambda self: self.env['ir.sequence'].next_by_code('pa.program.activity'))
    name = fields.Char("Activity Name", required=True)
    description = fields.Text("Activity Description")
    program_id = fields.Many2one('pa.program', string="Related Program")
    location = fields.Selection([('inside', 'Internal'), ('outside', 'External')], required=True, string="Activity Location")
    date_start = fields.Datetime("Activity Start Date")
    date_end = fields.Datetime("Activity End Date")
    analytic_account_id = fields.Many2one('account.analytic.account', string="Analytic Account")
    estimated_budget = fields.Float("Estimated Budget")
    active = fields.Boolean("Active", default=True)

    @api.model
    def create(self, vals):
        res = super().create(vals)  # ✅ fix
        if not res.analytic_account_id:
            account = self.env['account.analytic.account'].create({
                'name': res.name,
                'active': True,
            })
            res.analytic_account_id = account.id
        return res

    def write(self, vals):
        res = super().write(vals)  # ✅ same correction here
        for record in self:
            if not record.analytic_account_id:
                account = self.env['account.analytic.account'].create({
                    'name': record.name,
                    'active': True,
                })
                record.analytic_account_id = account.id
        return res


class PaProgramMedad(models.Model):
    _name = 'pa.program.medad'
    _description = 'Medad'
    _rec_name = 'name'

    code = fields.Char("Medad Code", required=True, copy=False, default=lambda self: self.env['ir.sequence'].next_by_code('pa.program.medad'))
    name = fields.Char("Medad Name", required=True)
    description = fields.Text("Medad Description")
    medad_type = fields.Selection([
        ('skills', 'Skills'),
        ('training', 'Training'),
        ('innovation', 'Innovation Support')
    ], string="Medad Type", required=True)
    activity_id = fields.Many2one('pa.program.activity', string="Associated Activity")
    analytic_account_id = fields.Many2one('account.analytic.account', string="Associated Analytic Account")
    estimated_budget = fields.Float("Estimated Budget")
    active = fields.Boolean("Active", default=True)

    @api.model
    def create(self, vals):
        res = super().create(vals)  # ✅ fix
        if not res.analytic_account_id:
            account = self.env['account.analytic.account'].create({
                'name': res.name,
                'active': True,
            })
            res.analytic_account_id = account.id
        return res

    def write(self, vals):
        res = super().write(vals)  # ✅ same correction here
        for record in self:
            if not record.analytic_account_id:
                account = self.env['account.analytic.account'].create({
                    'name': record.name,
                    'active': True,
                })
                record.analytic_account_id = account.id
        return res


# Example family/beneficiary for demo: you should replace with your actual model



class PaProgramActivityRegistration(models.Model):
    _name = 'pa.program.activity.registration'
    _description = 'Activity Registration'
    _inherit = ['mail.thread']

    name = fields.Char(string='Request Number', readonly=True, index=True,
                       default=lambda self: self.env['ir.sequence'].next_by_code('pa.program.activity.registration') or 'New')

    request_date = fields.Datetime(string='Request Date', default=fields.Datetime.now, readonly=True)
    creator_id = fields.Many2one('res.users', string='Creator', default=lambda self: self.env.user, readonly=True)

    date_from = fields.Datetime(string='Date From')
    date_to = fields.Datetime(string='Date To')

    familye_id = fields.Many2one('grant.benefit', string='Family')
    beneficiary_ids = fields.Many2many(
        'family.member',
        string='Beneficiary Name',
        domain="[('benefit_id', '=', familye_id)]"
    )
    benefit_category_id = fields.Many2one(related='familye_id.benefit_category_id', string='Family Category', readonly=True)

    # beneficiary_ids = fields.Many2many('family.member', string='Beneficiary Name')
    sms_phone = fields.Char(related='familye_id.sms_phone', string='Mobile Number', readonly=True)

    member_ids = fields.One2many(
        'family.member',
        'benefit_ids',
        string='Family Members'
    )

    branch_custom_id = fields.Many2one(string='Branch', related='familye_id.branch_custom_id', readonly=True)
    gender = fields.Selection(related='familye_id.gender', readonly=True)
    nationality_id = fields.Many2one(string='Nationality', related='familye_id.nationality_id', readonly=True)
    graduation_status = fields.Selection(string='Graduation Status', related='familye_id.graduation_status', readonly=True)
    health_status = fields.Selection(string='Health Status', related='familye_id.health_status', readonly=True)
    education_status = fields.Selection(string='Educational Status', related='familye_id.education_status', readonly=True)

    mother_is_life = fields.Boolean(string='Is Mother Alive?', related='familye_id.mother_is_life', readonly=True)
    mother_location_conf = fields.Many2one(string='Mother Location', related='familye_id.mother_location_conf', readonly=True)
    is_mother_work = fields.Boolean(string='Is Mother Working?', related='familye_id.is_mother_work', readonly=True)
    housing_type = fields.Selection(string='Housing Type', related='familye_id.housing_type', readonly=True)

    beneficiary_relation = fields.Selection([
        ('mother', 'Mother'),
        ('son', 'Son'),
        ('daughter', 'Daughter')
    ], string='Beneficiary Relation')



    sons = fields.Integer(
        string="Number of Sons",
        compute='_compute_sons_daughters',
        store=False
    )
    daughters = fields.Integer(
        string="Number of Daughters",
        compute='_compute_sons_daughters',
        store=False
    )

    return_reason = fields.Text(string='Return Reason')






    @api.depends('familye_id', 'familye_id.member_ids', 'familye_id.member_ids.relationn',
                 'familye_id.member_ids.relationn.relation_type')
    def _compute_sons_daughters(self):
        for rec in self:
            sons = 0
            daughters = 0
            members = rec.familye_id.member_ids.filtered(lambda m: m.relationn)
            for member in members:
                if member.relationn.relation_type == 'son':
                    sons += 1
                elif member.relationn.relation_type == 'daughter':
                    daughters += 1
            rec.sons = sons
            rec.daughters = daughters

    level_id = fields.Many2one('pa.program.level', string='Program Levels', required=True)
    track_id = fields.Many2one('pa.program.track', string='Program Tracks')
    program_id = fields.Many2one('pa.program', string='Programs')
    activity_id = fields.Many2one('pa.program.activity', string='Activities')
    medad_id = fields.Many2one('pa.program.medad', string='Medad')
    want_transport = fields.Selection([('yes', 'Yes'), ('no', 'No')], string='Does the beneficiary want transportation')

    state = fields.Selection([
        ('draft', 'Draft'),
        ('social_specialist', 'Social Specialist'),
        ('operation_manager', 'Operations Manager'),
        ('branch_manager', 'Branch Manager'),
        ('activity_head', 'Activity Head'),
        ('finance_manager', 'Finance Management'),
        ('approved', 'Approved'),
        ('refused', 'Refused')
    ], default='draft', tracking=True)

    rejection_reason = fields.Text(string='Rejection Reason')

    # To hold the last rejection note

    def unlink(self):
        for order in self:
            if order.state not in ['draft']:
                raise UserError(_('You cannot delete this record State not Draft'))
        return super(PaProgramActivityRegistration, self).unlink()

    @api.onchange('familye_id')
    def _onchange_familye_id(self):
        if self.familye_id:
            # Set member_ids to the current members of the selected familye_id
            # This links existing family.member records (no create)
            self.member_ids = [(6, 0, self.familye_id.member_ids.ids)]
        else:
            self.member_ids = [(5, 0, 0)]  # Clear if no familye_id

    # Validation of required fields based on level type
    @api.constrains('level_id', 'track_id', 'program_id', 'activity_id', 'medad_id')
    def _check_required_fields_based_on_level(self):
        for rec in self:
            if not rec.level_id:
                continue
            lvl_type = rec.level_id.type
            if lvl_type == 'route':  # مسارات
                if not rec.track_id or not rec.program_id:
                    raise ValidationError(_('لحالة المستوى "مسارات"، الحقول "المسار" و "البرنامج" مطلوبان'))
            elif lvl_type == 'activity':  # أنشطة
                if not rec.track_id or not rec.program_id or not rec.activity_id:
                    raise ValidationError(_('لحالة المستوى "أنشطة"، الحقول "المسار" و "البرنامج" و "النشاط" مطلوبة'))
            elif lvl_type == 'medad':  # مداد
                if not rec.track_id or not rec.program_id or not rec.activity_id or not rec.medad_id:
                    raise ValidationError(_('لحالة المستوى "مداد"، جميع الحقول "المسار"، "البرنامج"، "النشاط"، "المداد" مطلوبة'))

    def action_to_social_specialist(self):
        self.ensure_one()
        self.state = 'social_specialist'

    def action_approve(self):
        self.ensure_one()
        transition_map = {
            'social_specialist': 'operation_manager',
            'operation_manager': 'branch_manager',
            'branch_manager': 'activity_head',
            'activity_head': 'finance_manager',
            'finance_manager': 'approved',
        }
        next_state = transition_map.get(self.state)
        if next_state:
            self.state = next_state

    def action_refuse(self):
        self.ensure_one()
        self.state = 'refused'




    def action_reset_to_draft(self):
        self.ensure_one()
        self.state = 'draft'

    def action_return_to_specialist(self):
        self.ensure_one()
        self.state = 'social_specialist'


    def action_return_to_draft(self):
        # Open wizard to collect return reason - opens form view on 'empowerment.return.reason.wizard'
        return {
            'type': 'ir.actions.act_window',
            'name': _('سبب الإرجاع'),
            'view_mode': 'form',
            'res_model': 'pa.return.reason.wizard',
            'target': 'new',
            'context': {'default_registration_id': self.id}
        }


class PaReturnReasonWizard(models.TransientModel):
    _name = 'pa.return.reason.wizard'
    _description = 'Return Reason Wizard'

    reason = fields.Text(string='Return Reason', required=True)
    registration_id = fields.Many2one('pa.program.activity.registration', string='Registration Request')


    def action_confirm_return(self):
        if self.registration_id:
            self.registration_id.rejection_reason = self.reason
            # move back to draft or social_specialist depending on the context/state
            if self.registration_id.state == 'operation_manager':
                self.registration_id.state = 'social_specialist'
                self.registration_id.return_reason = self.reason
            else:
                self.registration_id.state = 'draft'
                self.registration_id.return_reason = self.reason

        return {'type': 'ir.actions.act_window_close'}

class PaProgram(models.Model):
    _name = 'pa.family'

class PaProgramType(models.Model):
    _name = 'pa.program.type'

    pg_type =fields.Char(string='Name')

class FamilyMember(models.Model):
    _inherit = 'family.member'

    benefit_ids = fields.Many2one(
        'pa.program.activity.registration',
        string='Benefit Registration',
        ondelete='cascade',
        index=True,
    )

    need_trans = fields.Boolean(string='Need Transportation')
    need_medicin = fields.Boolean(string='Need Medicien')
    need_mental_dis = fields.Boolean(string='Have Mental Disorders')

