from odoo import fields, models, api, _
from odoo.exceptions import UserError, ValidationError
from datetime import date, datetime, timedelta
from dateutil.relativedelta import relativedelta
from odoo.tools import html_escape, html2plaintext


class ServiceRequest(models.Model):
    _name = 'service.request'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _order = "date desc"

    name = fields.Char(string='Reference', required=True, copy=False, readonly=True, index=True,
                       default=lambda self: _('New'))
    benefit_type = fields.Selection(string='Benefit Type', selection=[('family', 'Family'), ('member', 'Member')])
    date = fields.Datetime(string='Request Date', default=fields.Datetime.now)
    marriage_contract_date = fields.Date(string="Marriage Contract Date")
    family_id = fields.Many2one('grant.benefit', string='Family',
                                domain="['|',('state','=','second_approve'),'&',('state','in',['waiting_approve','first_approve']),('action_type','=','suspended')]")
    researcher_id = fields.Many2one("committees.line", string="Researcher", related="family_id.researcher_id",
                                    store=True)
    family_category = fields.Many2one('benefit.category', string='Family Category',
                                      related='family_id.benefit_category_id', store=True)
    family_code = fields.Char(string='Family Code', related='family_id.code', store=True)
    benefit_member_count = fields.Integer(string="Benefit Member count", related='family_id.benefit_member_count',
                                          store=True)
    branch_custom_id = fields.Many2one('branch.settings', string="Branch", related='family_id.branch_custom_id',
                                       store=True)
    member_id = fields.Many2one('family.member', string='Member')
    member_domain_ids = fields.Many2many(comodel_name='family.member', compute='_compute_member_domain_and_count',
                                         string="Eligible Members", store=True)
    description = fields.Char(string='Description')
    need_status = fields.Selection(string='Need Status', selection=[('urgent', 'urgent'), ('not_urgent', 'Not urgent')])
    main_service_category = fields.Many2one('services.settings', domain="[('service_type','=','main_service')]",
                                            string="Main Service Category")
    sub_service_category = fields.Many2one('services.settings',
                                           domain="[('service_type','=','main_service'),('service_type','=',False),('parent_service','=',main_service_category)]",
                                           string='Sub Service Category')
    service_cat = fields.Many2one('services.settings', string='Service Cat.')
    available_service_cats = fields.Many2many('services.settings', compute='_compute_available_service_cats',
                                              store=True)
    service_attach = fields.Many2many('ir.attachment', 'rel_service_attachment_service_request', 'service_request_id',
                                      'attachment_id', string='Service Attachment')
    requested_service_amount = fields.Float(string="Requested Service Amount", copy=False, tracking=False)
    # yearly Estimated Rent Amount
    estimated_rent_amount = fields.Float(string="Estimated Rent Amount", compute="_get_estimated_rent_amount",
                                         store=True)
    # The value of payment by payment method(yearly-half-quartarly)
    estimated_rent_amount_payment = fields.Float(string="Estimated Rent Amount Payment",
                                                 compute="_get_estimated_rent_amount_payment", store=True)
    service_type = fields.Selection([('rent', 'Rent')], string='Service Type', related='service_cat.service_type')
    max_limit_period = fields.Selection(string='Maximum Limit Period', related='service_cat.max_limit_period')
    payment_method = fields.Selection([
        ('none', 'None'),
        ('payment_order', 'Payment Order'),
        ('invoice', 'Invoice'),
    ], string='Payment Method', related='service_cat.payment_method', store=True, default="payment_order")
    # is_alternative_housing = fields.Boolean(string='Is Alternative Housing?')
    rent_contract_number = fields.Char(string="Rent Contract Number", compute='_compute_rent_details', store=True)
    rent_start_date = fields.Date(string='Rent Start Date', compute='_compute_rent_details', store=True)
    rent_end_date = fields.Date(string='Rent End Date', compute='_compute_rent_details', store=True)
    rent_amount = fields.Float(string='Rent Amount', compute='_compute_rent_details', store=True)
    rent_amount_payment = fields.Float(string='Rent Amount Payment', compute='_get_rent_amount_payment', store=True)
    payment_type = fields.Selection(
        [
            ('1', 'Yearly'),
            ('2', 'Half-yearly'),
            ('4', 'Quarterly'),
            ('12', 'Monthly')
        ],
        string='Payment Type',
        compute='_compute_rent_details',
        store=True
    )
    rent_attachment = fields.Many2many('ir.attachment', 'rel_rent_attachment_service_request', 'service_request_id',
                                       'attachment_id', string='Rent Attachment', compute='_compute_rent_details',
                                       store=True)
    rent_payment_date = fields.Date(string='Rent Payment Date')
    rent_payment_date_exception = fields.Boolean(string='Rent Payment Date Exception?')
    start = fields.Date(string="Start Date")
    end = fields.Date(string='End Date')
    added_amount_if_mother_dead = fields.Float(string="Added Amount (If mother dead)",
                                               compute="_get_added_amount_if_mother_dead", store=True)
    attachment_lines = fields.One2many(
        'service.attachments.settings',
        'service_request_id',
        compute='_compute_attachment_lines',
        readonly=False,
        copy=False,
        store=True
    )
    account_id = fields.Many2one(
        'account.account',
        string='Expenses Account',
        compute="_compute_account_id"
    )
    device_account_id = fields.Many2one('account.account', string='Expenses Account', related='device_id.account_id')
    accountant_id = fields.Many2one('res.users', string='Accountant', related='service_cat.accountant_id', store=True)
    service_producer_id = fields.Many2one('res.partner', string='Service Producer', )
    is_service_producer = fields.Boolean(string='Is Service Producer?', related='service_cat.is_service_producer')
    # maintenance_items_id = fields.Many2one('home.maintenance.lines', string="Maintenance Items")
    maintenance_items_ids = fields.One2many('home.maintenance.items', 'service_request_id',
                                            string="Maintenance Items", )
    payment_order_ids = fields.Many2many(comodel_name='payment.orders', relation='service_request_payment_order_rel',
                                         column1='service_request_id',
                                         column2='payment_order_id', string='Payment Orders', copy=False, )
    payment_order_id = fields.Many2one('payment.orders', string='Payment Order', copy=False)
    payment_order_count = fields.Integer(compute='_compute_payment_order', string='Number of Payment Orders')
    is_payment_order_done = fields.Boolean(string='Is Payment Order Done?')
    aid_amount = fields.Float(string='Aid Amount', compute='_get_aid_amount')
    # Fields for alternative house
    providing_alternative_housing_based_rent = fields.Boolean(string='Providing alternative housing based on rent')
    rent_for_alternative_housing = fields.Many2one('services.settings', compute='_get_rent_for_alternative_housing')
    # Fields for electrical_devices service
    device_id = fields.Many2one('electrical.devices', string='Device',
                                domain="[('min_count_member','<=',benefit_member_count),('max_count_member','>=',benefit_member_count)]")
    electrical_device_line_ids = fields.One2many('electrical.device.line', 'service_request_id',
                                                 string='Electrical Devices', copy=False)
    vendor_bill = fields.Many2one('account.move', copy=False)
    requested_quantity = fields.Integer(string='Requested Quantity')
    exception_or_steal = fields.Boolean(string='Exception Or Steal?')
    exception_or_steal_attach = fields.Many2many('ir.attachment', 'rel_exception_or_steal_attachment_service_request',
                                                 'exception_or_steal_id', 'attachment_id',
                                                 string='Exception or steal Attachment')
    # Home furnishing Exception
    home_furnishing_exception = fields.Boolean(string='Exception(Fire Or Steal or Natural disaster)')
    furnishing_items_ids = fields.One2many('home.furnishing.items', 'service_request_id', string="Furnishing Items")
    # Marriage
    member_age = fields.Integer(string="Member Age", related="member_id.age")
    member_payroll = fields.Float(string="Member Payroll", related="member_id.member_income")
    has_marriage_course = fields.Selection(selection=[
        ('yes', 'Yes'),
        ('no', 'No'),
    ], string='Has Marriage Course')
    service_benefit_count = fields.Integer(string='Service Benefit Count', compute="_compute_member_domain_and_count")
    # Buy home
    amount_for_buy_home_for_member_count = fields.Float(string="Amount For Buy Home for member count")
    home_age = fields.Integer(string='Home Age')
    required_attach = fields.Boolean(string='Required Attach', related='service_cat.required_attach')
    state = fields.Selection(selection=[
        ('draft', 'Draft'),
        ('waiting_family', 'Waiting Family'),
        ('researcher', 'Researcher'),
        ('waiting_approve', 'Waiting for Operation Manager'),
        ('first_approve', 'Waiting for Branch Manager'),
        ('family_services_manager', 'Waiting Family Services Manager'),
        ('legal_department', 'Waiting Legal Department'),
        ('projects_department', 'Waiting Projects Department'),
        ('gm_assistant', 'Waiting Assistant General Manager'),
        ('accounting_approve', 'Accounting Approve'),
        ('return_to_bank', 'Return to Bank'),
        ('approval_of_beneficiary_services', 'Approval of beneficiary services'),
        ('send_request_to_supplier', 'Send Request To Supplier'),
        ('family_received_device', 'Family Received Device'),
        ('refused', 'Refused')
    ], string='state', default='draft', tracking=True, group_expand='_expand_states')
    # dynamic_state = fields.Selection(selection=[],string="State",default='draft',tracking=True,)
    state_a = fields.Selection(related='state', tracking=False)
    state_b = fields.Selection(related='state', tracking=False)
    refuse_reason_id = fields.Many2one('service.refuse.reason', string="Refuse Reason")
    return_reason = fields.Text(string="Reason for Returning the Request")
    refuse_reason = fields.Text(string="Reason for Refusal")
    specialist_note = fields.Text(string="Specialist's Note After Return")
    exception = fields.Boolean(string='Exception', default=False)
    exception_attach = fields.Many2many('ir.attachment', 'rel_exception_attachment_service_request',
                                        'service_request_id',
                                        'attachment_id', string='Exception Attachment')
    service_conditions = fields.Html(related='service_cat.service_conditions', string="Service Conditions")
    service_approval_date = fields.Datetime(string="Service Approval Date", readonly=True, )
    company_id = fields.Many2one('res.company', string="Company", default=lambda self: self.env.user.company_id)
    currency_id = fields.Many2one('res.currency', string="Currency", related='company_id.currency_id')
    service_max_amount = fields.Float(string="Maximum Amount", copy=False)
    rent_period = fields.Integer('Rent Period')
    is_orphan = fields.Boolean(string='Orphaned (Both Parents Deceased)', compute='_compute_is_orphan', store=True)
    has_money_for_payment_is_appearance = fields.Boolean(string='Has money Field is appearance?',
                                                         compute='_get_money_for_payment_is_appearance')
    has_money_for_payment = fields.Selection([('yes', 'Yes'), ('no', 'No')], string='Has money for payment?')
    has_money_to_pay_first_payment = fields.Selection([('yes', 'Yes'), ('no', 'No')],
                                                      string='Has money to pay first payment?')
    has_money_field_is_appearance = fields.Boolean(string='Has money Field is appearance?',
                                                   compute='_get_money_field_is_appearance')
    car_name = fields.Char(string='Car Name')
    car_owner_id = fields.Many2one('family.member', domain="[('benefit_id','=',family_id)]", string="Car Owner")
    car_model_id = fields.Many2one('benefit.vehicle.model', string='Car model')
    car_price = fields.Float(string='Car Price')
    car_remaining_amount = fields.Float(string='Remaining Amount', compute='_compute_remaining_amount', store=True, )
    show_car_remaining_amount = fields.Boolean(string='Show Car Remaining Amount', compute='_compute_remaining_amount')
    application_form = fields.Many2many('ir.attachment', 'request_application_form_rel', 'request_id', 'attachment_id',
                                        string="Application Form")
    driving_license = fields.Many2many('ir.attachment', 'request_driving_license_rel', 'request_id', 'attachment_id',
                                       string="Driving License")
    owner_identity = fields.Many2many('ir.attachment', 'request_owner_identity_rel', 'request_id', 'attachment_id',
                                      string="Owner Identity")
    is_driver_family_member = fields.Boolean(string="Is Driver Family Member?", default=True)
    driver_name = fields.Char(string="Driver Name")
    seasonal_service_id = fields.Many2one('seasonal.service', string='Seasonal Service', ondelete='cascade')
    is_seasonal = fields.Boolean(string='Is Seasonal Service?', related='service_cat.is_seasonal_service')
    is_in_kind = fields.Boolean(string="In Kind", default=False)
    service_qty = fields.Float(string='Quantity', default=1)
    payment_order_state = fields.Selection(string='Payment Order State', selection=[
        ('none', 'None'),
        ('waiting', 'Waiting Payment'),
        ('done', 'Done Payment'), ], copy=False, compute="_compute_payment_order_state", store=True)
    total_moves = fields.Integer(string="Total Move", compute='_get_total_move_lines')
    return_reason_id = fields.Many2one("return.reason", string="Return Reason")
    agree_terms = fields.Boolean(string="I agree to the Terms and Conditions", default=False, )
    related_information_html = fields.Html(string="Related Information",
                                           compute='_compute_related_information_html', store=True, )
    researcher_opinion = fields.Html(string='Specialist Opinion', tracking=True)
    allowed_product_ids = fields.Many2many('product.product', string='Allowed Products',
                                           compute='_compute_allowed_product_ids', store=True, )

    def action_create_project(self):
        pass

    def _check_required_attachments(self):
        self.ensure_one()
        current_state = self.state
        required_docs = self.attachment_lines.filtered(lambda l: l.state == current_state)
        missing_docs = required_docs.filtered(lambda l: not l.service_attach)
        if missing_docs:
            # missing_names = ", ".join(missing_docs.mapped('name'))
            missing_names = ", ".join([doc.name for doc in missing_docs if doc.name])
            raise UserError(
                _("Cannot proceed with approval. The following required documents for status '%(status)s' are missing: %(missing)s") % {
                    'status': dict(self._fields['state'].selection).get(current_state, current_state),
                    'missing': missing_names
                })

    @api.depends('service_cat', 'family_id', 'member_id', 'benefit_type')
    def _compute_related_information_html(self):
        for rec in self:
            if not rec.service_cat:
                no_service_title = _("No service selected")
                no_service_desc = _("Please select a service category to view related information.")
                rec.related_information_html = f"""
                        <div class="o_form_sheet_not_found">
                            <div class="o_form_sheet_not_found_icon">📋</div>
                            <h4>{no_service_title}</h4>
                            <p>{no_service_desc}</p>
                        </div>
                    """
                continue

            family_rows = []
            member_rows = []
            family_title = _("Family Information")
            member_title = _("Member Information")

            for ir_field in rec.service_cat.family_related_fields:
                row = rec._get_field_display_value(rec.family_id, ir_field)
                if row:
                    family_rows.append(row)
            if rec.benefit_type == 'member' and rec.member_id:
                for ir_field in rec.service_cat.member_related_fields:
                    row = rec._get_field_display_value(rec.member_id, ir_field)
                    if row:
                        member_rows.append(row)
            family_table = rec._build_info_table(family_title, family_rows)
            member_table = rec._build_info_table(member_title, member_rows) if member_rows else ""

            rec.related_information_html = f"""
                    <div class="info-container">
                        {family_table}
                        {member_table}
                    </div>
                """

    @api.onchange('is_driver_family_member')
    def _onchange_is_driver_family_member(self):
        for rec in self:
            if rec.is_driver_family_member:
                rec.driver_name = False
            else:
                rec.car_owner_id = False

    def _build_info_table(self, title, rows):
        field_name_label = _("Field Name")
        value_label = _("Value")
        no_info_text = _("No information available for this section.")
        if not rows:
            return f"""
                    <div class="info-section">
                        <h3>{title}</h3>
                        <div class="info-empty">{no_info_text}</div>
                    </div>
                """
        return f"""
                <div class="info-section">
                    <h3>{title}</h3>
                    <table class="table info-table">
                        <thead>
                            <tr>
                                <th>{field_name_label}</th>
                                <th>{value_label}</th>
                            </tr>
                        </thead>
                        <tbody>
                            {''.join(rows)}
                        </tbody>
                    </table>
                </div>
            """

    def _get_field_display_value(self, record, ir_field):
        if not record or not ir_field:
            return ""

        field_name = ir_field.name
        field = record._fields.get(field_name)
        if not field:
            return ""

        value = record[field_name]
        label = html_escape(ir_field.field_description or field_name)

        if value in (False, None, '') or (hasattr(value, '__len__') and len(value) == 0):
            display = '<span class="info-empty">—</span>'
        elif field.type == 'boolean':
            display = f"<span class='badge badge-success'>✓ {_('Yes')}</span>" if value else f"<span class='badge badge-danger'>✗ {_('No')}</span>"
        elif field.type == 'selection':
            sel_dict = dict(field._description_selection(record.env))
            display_val = sel_dict.get(value, value)
            display = f'<span class="badge">{html_escape(str(display_val or "—"))}</span>'
        elif field.type == 'many2one':
            display = f'<strong>{html_escape(value.name or "—")}</strong>'
        elif field.type == 'many2many':
            if field.comodel_name == 'ir.attachment':
                if not value:
                    display = '<span class="info-empty">—</span>'
                else:
                    links = []
                    for attach in value:
                        filename = attach.name or _("Unnamed file")
                        url = f"/web/content/{attach.id}?download=true"
                        links.append(f'<a class="file-link" href="{url}" target="_blank">📎 {html_escape(filename)}</a>')
                    display = '<br/>'.join(links)
            else:
                badges = [f'<span class="badge badge-secondary">{html_escape(r.name or "-")}</span>' for r in value]
                display = ' '.join(badges) or '<span class="info-empty">—</span>'
        elif field.type == 'one2many':
            items = [
                f'<div style="margin:8px 0; padding:6px 0; border-bottom:1px dotted #ddd;">• {html_escape(r.display_name or r.name or "-")}</div>'
                for r in value[:20]]
            more = f'<div style="color:#875A92; font-weight:600; margin-top:10px;">... {_("and")} {len(value) - 20} {_("more records")}</div>' if len(
                value) > 20 else ""
            display = ''.join(items) + more or '<span class="info-empty">—</span>'
        elif field.type == 'binary':
            if value:
                filename = getattr(record, f"{field_name}_fname", None) or _("Download file")
                url = f"/web/content/{record._name}/{record.id}/{field_name}?download=true"
                display = f'<a class="file-link" href="{url}" target="_blank">📎 {html_escape(filename)}</a>'
            else:
                display = '<span class="info-empty">—</span>'
        else:
            display = html_escape(str(value))

        return f"""
            <tr>
                <td class="info-label">{label}</td>
                <td class="info-value">{display}</td>
            </tr>
        """

    @api.depends('payment_order_ids')
    def _compute_payment_order(self):
        for rec in self:
            if rec.payment_order_ids:
                rec.payment_order_count = len(rec.payment_order_ids)
            else:
                rec.payment_order_count = 0

    @api.depends('payment_order_id', 'payment_order_id.state', 'vendor_bill', 'vendor_bill.state')
    def _compute_payment_order_state(self):
        for rec in self:
            payment_order_state = 'none'
            if rec.payment_order_id:
                if rec.payment_order_id.state == "done":
                    payment_order_state = "done"
                    rec.service_approval_date = fields.Datetime.now()
                    if rec.state == 'accounting_approve':
                        rec.state = 'send_request_to_supplier'
                    rec.is_payment_order_done = True
                else:
                    payment_order_state = "waiting"
            elif rec.vendor_bill:
                if rec.vendor_bill.state == "posted":
                    payment_order_state = "done"
                    rec.state = 'send_request_to_supplier'
                else:
                    payment_order_state = "waiting"
            rec.payment_order_state = payment_order_state

    @api.depends('car_price', 'requested_service_amount', 'service_cat')
    def _compute_remaining_amount(self):
        for rec in self:
            if rec.service_cat and rec.service_cat.service_type == 'buy_car':
                if rec.car_price and rec.requested_service_amount:
                    rec.car_remaining_amount = rec.car_price - rec.requested_service_amount
                    rec.show_car_remaining_amount = rec.car_price > rec.requested_service_amount
                else:
                    rec.car_remaining_amount = 0.0
                    rec.show_car_remaining_amount = False
            else:
                rec.car_remaining_amount = 0.0
                rec.show_car_remaining_amount = False

    def action_return_bank(self):
        self.ensure_one()
        return {
            'name': _("Bank Return"),
            'type': 'ir.actions.act_window',
            'res_model': 'return.reason.wizard',
            'view_mode': 'form',
            'target': 'new',
            'context': {
                'default_line_id': self.id,
                'default_line_model': 'service.request',
            }
        }

    def action_processed(self):
        for record in self:
            record.state = 'accounting_approve'

    @api.depends('requested_service_amount', 'service_max_amount')
    def _get_money_for_payment_is_appearance(self):
        for rec in self:
            if rec.requested_service_amount and rec.service_max_amount and rec.requested_service_amount > rec.service_max_amount:
                rec.has_money_for_payment_is_appearance = True
            else:
                rec.has_money_for_payment_is_appearance = False

    @api.depends('requested_service_amount', 'service_max_amount')
    def _get_money_field_is_appearance(self):
        for rec in self:
            if rec.requested_service_amount and rec.service_max_amount and rec.requested_service_amount > rec.service_max_amount:
                rec.has_money_field_is_appearance = True
            else:
                rec.has_money_field_is_appearance = False

    @api.depends('family_id.mother_marital_conf')
    def _compute_is_orphan(self):
        for rec in self:
            rec.is_orphan = bool(getattr(rec.family_id.mother_marital_conf, 'is_dead', False))

    def _expand_states(self, states, domain, order):
        return [key for key, val in type(self).state.selection]

    # TODO: remove this method
    @api.depends('service_cat')
    def _compute_account_id(self):
        for rec in self:
            rec.account_id = rec.service_cat.account_id

    @api.depends('service_cat')
    def _compute_attachment_lines(self):
        for rec in self:
            commands = [(5, 0, 0)]

            if rec.service_cat:
                for attachment_line in rec.service_cat.attachment_lines:
                    commands.append((0, 0, {
                        'service_id': False,
                        'service_request_id': rec.id,
                        'name': attachment_line.name,
                        'notes': attachment_line.notes,
                        'previous_service_attachment_settings_id': attachment_line.id,
                        'state': attachment_line.state,
                    }))

            rec.attachment_lines = commands

    @api.model
    def create(self, vals):
        res = super(ServiceRequest, self).create(vals)
        if not res.name or res.name == _('New'):
            res.name = self.env['ir.sequence'].sudo().next_by_code('service.request.sequence') or _('New')
        return res

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

    @api.depends('family_id', 'member_id', 'benefit_type')
    def _compute_rent_details(self):
        for rec in self:
            contract = False

            if rec.benefit_type == 'family' and rec.family_id:
                contract = rec.family_id.current_rent_contract_id
            elif rec.benefit_type == 'member' and rec.member_id:
                member_contracts = rec.family_id.rent_contract_ids.filtered(
                    lambda c: c.state == 'active' and c.member_id == rec.member_id and c.landlord_type == 'member'
                ).sorted('start_date', reverse=True)
                contract = member_contracts[:1] or False

            if contract:
                rec.rent_contract_number = contract.name
                rec.rent_start_date = contract.start_date
                rec.rent_end_date = contract.end_date
                rec.rent_amount = contract.rent_amount
                rec.payment_type = contract.payment_type
                rec.rent_attachment = [(6, 0, contract.contract_attachment.ids)]
            else:
                rec.rent_contract_number = False
                rec.rent_start_date = False
                rec.rent_end_date = False
                rec.rent_amount = 0.0
                rec.payment_type = False
                rec.rent_attachment = [(5, 0, 0)]

    def _get_aid_amount(self):
        for rec in self:
            if rec.service_type == 'rent':
                rec.aid_amount = rec.requested_service_amount + rec.added_amount_if_mother_dead
            else:
                rec.aid_amount = rec.requested_service_amount

    def _get_rent_for_alternative_housing(self):
        for rec in self:
            if rec.service_cat.service_type == 'alternative_housing':
                rec.rent_for_alternative_housing = self.env['services.settings'].search([('service_type', '=', 'rent')],
                                                                                        limit=1).id
            else:
                rec.rent_for_alternative_housing = False

    @api.depends('family_id', 'service_cat')
    def _compute_member_domain_and_count(self):
        for rec in self:
            if not rec.family_id:
                rec.member_domain_ids = False
                rec.service_benefit_count = 1
                continue

            family_members = rec.family_id.member_ids
            benefit_members = family_members.filtered(lambda m: m.member_status == 'benefit')
            count = 1

            if rec.benefit_type == "family":
                count_members = benefit_members
                if rec.service_cat.max_age > 0:
                    count_members = family_members.filtered(
                        lambda m: m.age <= rec.service_cat.max_age
                    )

                count = len(count_members)

            domain_members = family_members

            if rec.service_cat:
                sc = rec.service_cat
                if not sc.allow_non_beneficiary:
                    domain_members = benefit_members
                if sc.is_this_service_for_student:
                    domain_members = domain_members.filtered(
                        lambda m: (
                                m.education_status == 'educated'
                                and any(edu.case_study == 'continuous'
                                        for edu in m.member_education_status_ids)
                        )
                    )
                if rec.benefit_type == "family":
                    count = len(domain_members)

            rec.service_benefit_count = count
            rec.member_domain_ids = domain_members

    def action_send_to_researcher(self):
        for rec in self:
            rec._check_required_attachments()
            if rec.service_cat and rec.service_cat.service_type == 'home_furnishing':
                for item in rec.furnishing_items_ids:
                    max_amount = item.home_furnishing_items.max_furnishing_amount or 0.0
                    if 0 < max_amount < item.furnishing_cost:
                        if not item.price_first_attach:
                            raise ValidationError(
                                _("Cannot send to researcher!\n\n"
                                  "Item '%(item)s': Cost (%(cost).2f) exceeds max limit (%(max).2f).\n"
                                  "→ First price attachment is mandatory.") % {
                                    'item': item.home_furnishing_items.name,
                                    'cost': item.furnishing_cost,
                                    'max': max_amount
                                }
                            )

                        if not item.price_second_attach:
                            raise ValidationError(
                                _("Cannot send to researcher!\n\n"
                                  "Item '%(item)s': Cost (%(cost).2f) exceeds max limit (%(max).2f).\n"
                                  "→ Second price attachment is mandatory.") % {
                                    'item': item.home_furnishing_items.name,
                                    'cost': item.furnishing_cost,
                                    'max': max_amount
                                }
                            )
            rec.state = 'researcher'

    def action_return_to_family(self):
        for rec in self:
            rec.state = 'waiting_family'

    def action_researcher_send_request(self):
        for rec in self:
            if not html2plaintext(rec.researcher_opinion or '').strip():
                raise ValidationError(
                    _('Please write the specialist opinion before completing the action.')
                )
            if not rec.requested_service_amount or rec.requested_service_amount <= 0:
                raise UserError(_("Please enter a valid service amount."))

            rec._check_required_attachments()
            rec.state = 'waiting_approve'

    def action_operations_chief_approve(self):
        for rec in self:
            rec._check_required_attachments()
            rec.state = 'first_approve'

    def action_branch_manager_approve(self):
        for rec in self:
            rec._check_required_attachments()
            if rec.service_cat.needs_services_head_approval or rec.exception:
                rec.state = 'family_services_manager'
            else:
                rec.state = 'accounting_approve'

    def action_family_services_manager_approve(self):
        for rec in self:
            rec._check_required_attachments()
            if rec.service_cat.needs_legal_approval:
                rec.state = 'legal_department'
            elif rec.service_cat.needs_project_management_approval:
                rec.action_create_project()
                rec.state = 'projects_department'
            elif rec.service_cat.needs_beneficiary_manager_approval or rec.exception:
                rec.state = 'gm_assistant'
            else:
                rec.state = 'accounting_approve'

    def action_legal_department_approve(self):
        for rec in self:
            rec._check_required_attachments()
            if rec.service_cat.needs_project_management_approval:
                rec.action_create_project()
                rec.state = 'projects_department'
            elif rec.service_cat.needs_beneficiary_manager_approval or rec.exception:
                rec.state = 'gm_assistant'

    def action_projects_department_approve(self):
        for rec in self:
            rec._check_required_attachments()
            if rec.service_cat.needs_beneficiary_manager_approval or rec.exception:
                rec.state = 'gm_assistant'
            else:
                rec.state = 'accounting_approve'

    def action_beneficiary_manager_approve(self):
        for rec in self:
            rec._check_required_attachments()
            rec.state = 'accounting_approve'

    def action_accounting_approve(self):
        for rec in self:
            rec._check_required_attachments()
            if rec.service_type == 'electrical_devices':
                rec.state = 'approval_of_beneficiary_services'
            else:
                rec.service_approval_date = fields.Datetime.now()
                rec.state = 'send_request_to_supplier'

    def action_supplier_approve(self):
        for rec in self:
            rec._check_required_attachments()
            rec.service_approval_date = fields.Datetime.now()
            rec.state = 'send_request_to_supplier'

    def action_request_done(self):
        for rec in self:
            if rec.service_type == 'buy_car':
                car_vals = {
                    'benefit_id': rec.family_id.id,
                    'name': rec.car_name,
                    'member_id': rec.car_owner_id.id,
                    'car_model': rec.car_model_id.id,
                    'is_driver_family_member': rec.is_driver_family_member,
                    'driver_name': rec.driver_name,
                    'purchased_by_association': True,
                }
                car = self.env['cars.line'].create(car_vals)
                if rec.application_form:
                    car.application_form = [(6, 0, rec.application_form.ids)]
                if rec.driving_license:
                    car.driving_license = [(6, 0, rec.driving_license.ids)]
                if rec.owner_identity:
                    car.owner_identity = [(6, 0, rec.owner_identity.ids)]
                rec.family_id.has_car = True
            rec.state = 'family_received_device'

    def action_send_request_to_supplier(self):
        for rec in self:
            rec.state = 'family_received_device'

    def action_first_refuse(self):
        return {
            'name': _('Reason for Returning the Request'),
            'type': 'ir.actions.act_window',
            'res_model': 'reason.for.return.wizard',
            'view_mode': 'form',
            'target': 'new',
        }

    def action_refuse(self):
        return {
            'name': _('Refuse Reason'),
            'type': 'ir.actions.act_window',
            'res_model': 'service.refuse.reason.wizard',
            'view_mode': 'form',
            'target': 'new',
        }

    @api.onchange('rent_payment_date')
    def onchange_rent_payment_date(self):
        today_date = fields.Date.today()
        for rec in self:
            if rec.rent_payment_date and not rec.rent_payment_date_exception:
                month_before_rent_payment_date = rec.rent_payment_date - timedelta(days=30)
                if today_date > month_before_rent_payment_date:
                    raise UserError(_("You Should request At least a month ago rent payment date"))

    @api.onchange('furnishing_items_ids')
    def _onchange_home_furnishing_cost(self):
        furnishing_cost_sum = 0
        for rec in self.furnishing_items_ids:
            furnishing_cost_sum += rec.furnishing_cost
        self.requested_service_amount = furnishing_cost_sum

    @api.onchange('family_id', 'service_cat')
    def _onchange_member(self):
        for rec in self:
            if rec.service_cat:
                rec.benefit_type = rec.service_cat.benefit_type
                if rec.family_id.branch_family_id.service_producer_id and rec.service_type == 'electrical_devices':
                    rec.service_producer_id = rec.family_id.branch_family_id.service_producer_id
                else:
                    rec.service_producer_id = rec.service_cat.service_producer_id
            else:
                rec.benefit_type = False
                rec.service_producer_id = False

            if not rec.family_id:
                rec.member_id = False
                rec.service_cat = False
                rec.available_service_cats = False

            if rec.electrical_device_line_ids:
                rec.electrical_device_line_ids = [(5, 0, 0)]

    @api.onchange('start', 'end', 'rent_start_date', 'rent_end_date', 'payment_type')
    def _check_date_range(self):
        for rec in self:
            if rec.service_type != 'rent':
                continue
            months_map = {
                '1': 12,
                '2': 6,
                '4': 3,
                '12': 1
            }
            if rec.payment_type and rec.start:
                months_to_add = months_map.get(rec.payment_type)
                if months_to_add:
                    rec.end = rec.start + relativedelta(months=months_to_add, days=-1)

            contract = rec.family_id.current_rent_contract_id if rec.benefit_type == 'family' else False
            if rec.benefit_type == 'member' and rec.member_id:
                member_contracts = rec.family_id.rent_contract_ids.filtered(
                    lambda c: c.state == 'active' and c.member_id == rec.member_id and c.landlord_type == 'member'
                ).sorted('start_date', reverse=True)
                contract = member_contracts[:1] or False

            if contract:
                if contract.contract_type == 'fixed':
                    if rec.start and rec.end and rec.rent_start_date and rec.rent_end_date:
                        if not (rec.rent_start_date <= rec.start <= rec.rent_end_date and
                                rec.rent_start_date <= rec.end <= rec.rent_end_date):
                            raise UserError(
                                _("Requested rent period must be fully within the contract period "
                                  "because the contract is fixed-term.")
                            )
                else:
                    if rec.start and rec.rent_start_date:
                        if rec.start <= rec.rent_start_date:
                            raise UserError(
                                _("Requested start date cannot be before the contract start date.")
                            )
            if rec.payment_type and rec.start and rec.end:
                allowed_months = months_map.get(rec.payment_type)
                if not allowed_months:
                    continue

                diff = relativedelta(rec.end, rec.start)
                months_diff = diff.years * 12 + diff.months + 1

                if months_diff != allowed_months:
                    raise UserError(_(
                        "Payment Type requires a period of %s months, but selected period is %s months."
                        % (allowed_months, months_diff)
                    ))

    @api.onchange(
        'requested_service_amount',
        'benefit_type', 'date',
        'service_cat', 'family_id',
        'member_id', 'exception_or_steal',
        'home_furnishing_exception',
        'has_marriage_course', 'home_age',
        'amount_for_buy_home_for_member_count',
        'marriage_contract_date',
        'start', 'end',
        'electrical_device_line_ids'
    )
    def onchange_requested_service_amount(self):
        res = {}
        Service = self.env['service.request']
        today = fields.Date.today()
        date_before_year = today - timedelta(days=365)

        for rec in self:
            if not rec.exception and not rec.exception_attach:
                family_id = rec.family_id.id
                service_type = rec.service_cat.service_type
                allowed = rec.service_cat.allowed_recurrence
                interval = rec.service_cat.recurrence_interval or 1
                period = rec.service_cat.recurrence_period or 'months'
                max_limit_type = rec.service_cat.max_limit_type
                special_services = ['electrical_devices', 'alternative_housing']
                base_domain = [('family_id', '=', family_id), ('service_cat', '=', rec.service_cat.id),
                               ('id', '!=', rec._origin.id), ('state', '!=', 'refused')]
                if rec.benefit_type == "member":
                    base_domain.append(('member_id', '=', rec.member_id.id))
                if rec.service_cat.service_type == 'buy_car':
                    if rec.family_id.has_car:
                        raise ValidationError(_("You cannot request this service because you have a car."))
                    if rec.benefit_member_count < rec.service_cat.min_count_member:
                        raise ValidationError(
                            _("You cannot request this service because you are less than %s") % rec.service_cat.min_count_member)
                if rec.service_cat.service_type == 'recruiting_driver':
                    if not rec.family_id.has_car:
                        raise ValidationError(_("You cannot request this service because you do not have a car"))
                    # son_members_above_age = rec.family_id.member_ids.filtered(
                    #    lambda x: x.relationn.relation_type == 'son' and x.age > 18)
                    # daughter_members_above_age = rec.family_id.member_ids.filtered(
                    #    lambda x: x.relationn.relation_type == 'daughter' and x.age > 18)

                    children_above_18_living_with_family = rec.family_id.member_ids.filtered(
                        lambda m: m.relationn.relation_type in ('son', 'daughter')
                                  and m.age > 18
                                  and not m.member_location_conf.is_far_from_family
                    )

                    if children_above_18_living_with_family:
                        raise ValidationError(
                            _("You cannot request this service because there is at least one child over 18 years old living with the family.")
                        )

                    disable_mother = rec.family_id.member_ids.filtered(
                        lambda x: x.relationn.relation_type == 'mother' and bool(x.disabilities_attachment_ids))
                    work_mother = rec.family_id.member_ids.filtered(
                        lambda x: x.relationn.relation_type == 'mother' and x.is_work)
                    disable_replacement_mother = rec.family_id.member_ids.filtered(
                        lambda x: x.relationn.relation_type == 'replacement_mother' and bool(
                            x.disabilities_attachment_ids))
                    work_replacement_mother = rec.family_id.member_ids.filtered(
                        lambda x: x.relationn.relation_type == 'replacement_mother' and x.is_work)
                    # if son_members_above_age or daughter_members_above_age:
                    #    raise ValidationError(
                    #        _("You cannot request this service because children above 18 years"))
                    if rec.family_id.add_replacement_mother and not disable_replacement_mother and not work_replacement_mother:
                        raise ValidationError(
                            _("You cannot request this service because mother should be worked or has disability"))
                    if not rec.family_id.add_replacement_mother and not disable_mother and not work_mother:
                        raise ValidationError(
                            _("You cannot request this service because mother should be worked or has disability"))
                if service_type in ['home_maintenance', 'complete_building_house', 'buy_home']:
                    existing_request_restoration = Service.search([
                        ('family_id', '=', family_id),
                        ('service_cat.service_type', '=', 'home_restoration'),
                        ('id', '!=', rec._origin.id),
                        ('state', '!=', 'refused')
                    ], order='date desc', limit=1)

                    if service_type == 'buy_home':
                        complete_building_requests = Service.search([
                            ('family_id', '=', family_id),
                            ('service_cat.service_type', '=', 'complete_building_house'),
                            ('id', '!=', rec._origin.id),
                            ('state', '!=', 'refused')
                        ], order='date desc', limit=1)
                        if complete_building_requests and complete_building_requests.date:
                            raise UserError(_(
                                "You cannot request 'buy_home' service because there is an existing 'complete_building_house' service request."
                            ))
                    if service_type == 'complete_building_house':
                        buy_home_requests = Service.search([
                            ('family_id', '=', family_id),
                            ('service_cat.service_type', '=', 'buy_home'),
                            ('id', '!=', rec._origin.id),
                            ('state', '!=', 'refused')
                        ], order='date desc', limit=1)
                        if buy_home_requests and buy_home_requests.date:
                            raise UserError(_(
                                "You cannot request 'complete_building_house' service because there is an existing 'buy_home' service request."
                            ))
                    if existing_request_restoration and existing_request_restoration.date:
                        if service_type == 'buy_home':
                            raise ValidationError(_(
                                "You cannot request this service together with 'home_restoration' within the same recurrence period."
                            ))
                        else:
                            restoration_date = existing_request_restoration.date.date()
                            next_allowed_restoration_date = (
                                restoration_date + relativedelta(months=interval)
                                if period == 'months'
                                else restoration_date + relativedelta(years=interval)
                            )

                            if rec.date.date() < next_allowed_restoration_date:
                                raise ValidationError(_(
                                    "You cannot request this service together with 'home_restoration' within the same recurrence period."
                                ))
                if service_type == 'transportation_insurance':
                    if rec.family_id.has_car:
                        raise ValidationError(_("You cannot request this service because you have a car."))
                if service_type == 'buy_home':
                    if rec.service_cat.buy_home_max_total_amount < rec.amount_for_buy_home_for_member_count:
                        raise ValidationError(_(
                            "You can request this service because the total housing amount (%.2f) "
                            "is still under the maximum limit of %.2f."
                        ) % (rec.amount_for_buy_home_for_member_count, rec.service_cat.buy_home_max_total_amount))
                    if rec.home_age > rec.service_cat.home_age:
                        raise ValidationError(
                            _("You cannot request this service Again Because the home Age More than %s") % rec.service_cat.home_age)

                if rec.start and rec.end:
                    if rec.start > rec.end:
                        raise ValidationError(_("Start date must be before end date."))
                    overlap_domain = base_domain + [
                        ('start', '!=', False),
                        ('end', '!=', False),
                        ('start', '<=', rec.end),
                        ('end', '>=', rec.start)
                    ]
                    overlap_requests = Service.search(overlap_domain)
                    if overlap_requests:
                        raise ValidationError(
                            _("This service request overlaps with an existing requests [%s] for the same service "
                              "between %s and %s.") % (", ".join(overlap_requests.mapped('name')), rec.start, rec.end)
                        )

                if allowed:
                    if allowed == 'unlimited':
                        pass
                    elif allowed == 'once':
                        if Service.search_count(base_domain):
                            raise ValidationError(_("You cannot request this service more than once."))
                    else:
                        if service_type in special_services:
                            if service_type == 'electrical_devices':
                                if not rec.electrical_device_line_ids:
                                    rec.service_max_amount = 0.0
                                    rec.requested_service_amount = 0.0
                                    continue

                                total_amount = sum(rec.electrical_device_line_ids.mapped('subtotal'))
                                rec.requested_service_amount = total_amount
                                rec.service_max_amount = total_amount

                                delta_kwargs = {period: interval}
                                date_before = rec.date - relativedelta(**delta_kwargs)
                                device_qty_map = {}
                                for line in rec.electrical_device_line_ids:
                                    if line.device_id:
                                        device_id = line.device_id.id
                                        device_qty_map[device_id] = device_qty_map.get(device_id, 0) + line.quantity

                                for device_id, current_total_qty in device_qty_map.items():
                                    device = self.env['electrical.devices'].browse(device_id)
                                    allowed_qty = device.allowed_quantity
                                    if current_total_qty > allowed_qty:
                                        raise ValidationError(_(
                                            "Device '%s': Total quantity in this request (%s) exceeds the allowed limit of %s units."
                                        ) % (device.device_name, current_total_qty, allowed_qty))
                                    if not rec.exception_or_steal:
                                        domain = base_domain + [
                                            ('date', '>', date_before),
                                            ('electrical_device_line_ids.device_id', '=', device_id),
                                            ('exception_or_steal', '=', False)
                                        ]
                                        existing_requests = Service.search(domain)
                                        existing_device_lines = existing_requests.mapped(
                                            'electrical_device_line_ids').filtered(
                                            lambda l: l.device_id.id == device_id
                                        )
                                        total_previous_qty = sum(existing_device_lines.mapped('quantity'))
                                        total_qty = total_previous_qty + current_total_qty

                                        if total_qty > allowed_qty:
                                            raise ValidationError(_(
                                                "Device '%s': You cannot request more than %s units within %s %s. "
                                                "(Previous requests: %s, Current request: %s, Total: %s)"
                                            ) % (device.device_name, allowed_qty, interval,
                                                 period, total_previous_qty, current_total_qty, total_qty))
                        else:
                            last_request = Service.search(base_domain, order='date desc', limit=1)
                            if last_request and last_request.date:
                                last_date = (
                                    last_request.date.date()
                                    if isinstance(last_request.date, datetime)
                                    else last_request.date
                                )
                                next_allowed_date = (
                                    last_date + relativedelta(months=interval)
                                    if period == 'months'
                                    else last_date + relativedelta(years=interval)
                                )
                                if isinstance(next_allowed_date, datetime):
                                    next_allowed_date = next_allowed_date.date()

                                if rec.date.date() < next_allowed_date:
                                    raise ValidationError(_(
                                        "You can only request this service again after %s."
                                    ) % next_allowed_date.strftime('%Y-%m-%d'))

                if max_limit_type and service_type not in special_services:
                    if max_limit_type == 'fixed':
                        rec.service_max_amount = rec.service_cat.max_amount
                    elif max_limit_type == 'category':
                        rec.service_max_amount = rec.service_cat.category_amount_lines and max(
                            rec.service_cat.category_amount_lines.filtered(
                                lambda r: r.benefit_category_id.id == rec.family_category.id).mapped('max_amount'),
                            default=0.0) or 0
                    elif max_limit_type == 'category_person':
                        rec.service_max_amount = rec.service_cat.bill_lines and max(rec.service_cat.bill_lines.filtered(
                            lambda x: x.benefit_category_id.id == rec.family_category.id and
                                      x.min_count_member <= rec.benefit_member_count <= x.max_count_member).mapped(
                            'max_amount_for_bill'), default=0.0) or 0
                    elif max_limit_type == 'service':
                        pass
                    elif max_limit_type == 'none':
                        pass
                    elif max_limit_type == 'amount_person':
                        rec.service_max_amount = rec.service_cat.limit_person_line_ids and max(
                            rec.service_cat.limit_person_line_ids.filtered(
                                lambda
                                    x: x.min_count_member <= rec.benefit_member_count <= x.max_count_member)).amount or 0
                    elif max_limit_type == 'region':
                        rec.service_max_amount = rec.estimated_rent_amount / 12

                if rec.max_limit_period:
                    period_domain = base_domain.copy()
                    if service_type == 'home_furnishing' and not rec.home_furnishing_exception:
                        period_domain += [('home_furnishing_exception', '=', False)]
                    if rec.max_limit_period == "month":
                        if rec.start and rec.end:
                            start_date = rec.start.date() if isinstance(rec.start, datetime) else rec.start
                            end_date = rec.end.date() if isinstance(rec.end, datetime) else rec.end
                            diff = relativedelta(end_date, start_date)
                            num_months = diff.years * 12 + diff.months
                            if end_date > (start_date + relativedelta(months=rec.service_cat.max_months_limit)):
                                raise ValidationError(
                                    _("You cannot request this service for more than %s months.") % rec.service_cat.max_months_limit
                                )
                            if diff.days > 0:
                                num_months += 1

                            rec.service_max_amount *= num_months
                            if service_type == 'rent':
                                rec.service_max_amount += rec.added_amount_if_mother_dead
                                rec.requested_service_amount = min(rec.rent_amount_payment,
                                                                   rec.estimated_rent_amount_payment + rec.added_amount_if_mother_dead)
                    elif rec.max_limit_period == "calendar_year":
                        current_date = rec.date.date() if isinstance(rec.date, datetime) else rec.date
                        allowed_years = rec.service_cat.allowed_period or 1
                        start_year = current_date.year - (allowed_years - 1)
                        end_year = current_date.year

                        year_start = date(start_year, 1, 1)
                        year_end = date(end_year, 12, 31)

                        period_domain += [
                            ('date', '>=', datetime.combine(year_start, datetime.min.time())),
                            ('date', '<=', datetime.combine(year_end, datetime.max.time())),
                        ]

                        existing_requests = Service.search(period_domain)
                        total_spent = sum(existing_requests.mapped('requested_service_amount'))

                        rec.service_max_amount -= total_spent
                    elif rec.max_limit_period == "year_from_request":
                        current_date = rec.date.date() if isinstance(rec.date, datetime) else rec.date
                        allowed_years = rec.service_cat.allowed_period or 1
                        period_start_date = current_date - relativedelta(years=allowed_years)
                        period_end_date = current_date

                        period_domain += [
                            ('date', '>=', datetime.combine(period_start_date, datetime.min.time())),
                            ('date', '<=', datetime.combine(period_end_date, datetime.max.time())),
                        ]

                        existing_requests = Service.search(period_domain)
                        total_spent = sum(existing_requests.mapped('requested_service_amount'))
                        rec.service_max_amount -= total_spent
                    elif rec.max_limit_period == "individual":
                        rec.service_max_amount *= rec.service_benefit_count
                if rec.service_cat.service_type == 'marriage':
                    if rec.marriage_contract_date and rec.date:
                        request_date = rec.date.date() if isinstance(rec.date, datetime) else rec.date
                        contract_date = rec.marriage_contract_date
                        diff_days = (request_date - contract_date).days
                        if diff_days > 365:
                            raise ValidationError(
                                _("You cannot request this service because the marriage contract date exceeds one year."))
                    rec.service_max_amount = rec.service_cat.fatherless_member_amount
                    if rec.is_orphan:
                        rec.service_max_amount = rec.service_cat.orphan_member_amount
                    rec.requested_service_amount = rec.service_max_amount
                    if rec.member_age > rec.service_cat.max_age:
                        raise ValidationError(_("Member Age should be less than %s ") % rec.service_cat.max_age)
                    if rec.member_id.is_work and rec.member_payroll > rec.service_cat.member_max_payroll:
                        raise ValidationError(
                            _("Member Payroll should be less than %s ") % rec.service_cat.member_max_payroll)
                    if not rec.is_orphan and rec.requested_service_amount > rec.service_max_amount:
                        raise ValidationError(_("You cannot request more than %s ") % rec.service_max_amount)
                    if rec.is_orphan and rec.requested_service_amount > rec.service_max_amount:
                        raise ValidationError(_("You cannot request more than %s ") % rec.service_max_amount)
                    if rec.has_marriage_course == 'no':
                        raise UserError(_("You Should take a course"))
                    continue
                if service_type == 'home_furnishing':
                    if rec.home_furnishing_exception:
                        rec.service_max_amount = rec.service_cat.max_furnishing_amount_if_exception

                if rec.requested_service_amount > rec.service_max_amount and service_type not in special_services and not max_limit_type == 'none':
                    raise ValidationError(
                        _("You cannot request more than %s") % rec.service_max_amount
                    )

                if rec.benefit_type == 'family' and rec.service_cat.service_type == 'alternative_housing' and not rec.providing_alternative_housing_based_rent:
                    if rec.requested_service_amount > rec.service_cat.rent_amount_for_alternative_housing:
                        raise UserError(
                            _("You Cannot request amount more than %s") % rec.service_cat.rent_amount_for_alternative_housing)
                    elif rec.rent_period > rec.service_cat.rent_period:
                        raise UserError(
                            _("You Cannot request this service for period more than %s") % rec.service_cat.rent_period)

    @api.onchange('member_id')
    def onchange_member_id(self):
        for rec in self:
            if rec.member_id and rec.service_type == 'rent' and not rec.member_id.member_location_conf.is_far_from_family:
                raise UserError(_("You Cannot request Service if you not study inside Saudi Arabia"))

    @api.depends('family_category')
    def _compute_available_service_cats(self):
        for rec in self:
            domain = [('is_seasonal_service', '=', False), ('service_type', '!=', 'main_service'),
                      ('benefit_category_ids', 'in', [rec.family_category.id])]

            if rec.family_id:
                mother_country = rec.family_id.mother_country_id
                father_country = rec.family_id.father_country_id

                country_domain = [
                    '|',
                    ('allowed_country_ids', '=', False),
                    '|',
                    ('allowed_country_ids', 'in', [mother_country.id] if mother_country else []),
                    ('allowed_country_ids', 'in', [father_country.id] if father_country else [])
                ]

                allowed_services = self.env['services.settings'].search(country_domain)

                domain.append(('id', 'in', allowed_services.ids if allowed_services else []))

            if rec.family_id.property_type_id:
                if rec.family_id.property_type_code != 'ownership':
                    domain.append(('service_type', '!=', 'home_restoration'))
                else:
                    domain.append(('service_type', '!=', 'buy_home'))

                unavailable_services = rec.family_id.property_type_id.unavailable_service_ids
                if unavailable_services:
                    domain.append(('id', 'not in', unavailable_services.ids))

            rec.available_service_cats = rec.available_service_cats.sudo().search(domain)

    @api.depends('service_cat', 'benefit_member_count')
    def _compute_allowed_product_ids(self):
        for rec in self:
            if not rec.service_cat or not rec.benefit_member_count or rec.service_cat.service_type != 'electrical_devices':
                rec.allowed_product_ids = False
                continue

            matching_devices = rec.service_cat.electrical_devices_lines.filtered(
                lambda dev: (dev.min_count_member or 0) <= rec.benefit_member_count <= (dev.max_count_member or 9999)
            )

            rec.allowed_product_ids = matching_devices.mapped('product_ids')

    def action_set_to_draft(self):
        for rec in self:
            rec.state = 'draft'

    def action_accounting_transfer(self):
        validation_setting = self.env["family.validation.setting"].search([], limit=1)
        line_ids = []
        service_cats = self.mapped('service_cat')
        if len(service_cats) > 1:
            cat_names = ", ".join(service_cats.mapped('service_name'))
            raise UserError(_(
                "All selected service requests must belong to the same Service Cat.\n\n"
                "Selected Services Cat:\n%s"
            ) % cat_names)

        if service_cats.payment_method == "payment_order":
            invalid_records = self.filtered(
                lambda r: r.state != 'accounting_approve'
                          or r.payment_order_state != 'none'
                          or r.payment_order_id
            )

            if invalid_records:
                names = ", ".join(invalid_records.mapped('name'))
                raise UserError(_(
                    "The following service requests do not meet the conditions:\n%s\n"
                    "Each request must:\n"
                    "• Be in 'Accounting Approve' state\n"
                    "• Have payment order state = 'None'\n"
                    "• Not be linked to any payment order"
                ) % names)

            payment_order = self.env['payment.orders'].create({
                'state': 'draft',
                'accountant_id': service_cats.accountant_id.id,
                'service_requests_ids': [(6, 0, self.ids)],
                'type': 'services',
                'payment_order_description': service_cats.id,
            })
            self.write({
                'payment_order_ids': [(4, payment_order.id)],
                'payment_order_id': payment_order.id,
            })

        elif service_cats.payment_method == "invoice":
            missing_producer = self.filtered(lambda r: not r.service_producer_id)
            if missing_producer:
                names = ", ".join(missing_producer.mapped('name'))
                raise UserError(_(
                    "The following service requests do not have a Service Producer defined:\n%s"
                ) % names)
            invalid_records = self.filtered(
                lambda r: r.state != 'accounting_approve'
                          or r.payment_order_state != 'none'
                          or r.vendor_bill
            )

            if invalid_records:
                names = ", ".join(invalid_records.mapped('name'))
                raise UserError(_(
                    "The following service requests do not meet the conditions:\n%s\n"
                    "Each request must:\n"
                    "• Be in 'Accounting Approve' state\n"
                    "• Have payment order state = 'None'\n"
                    "• Not be linked to any invoice"
                ) % names)

            empty_requests = self.filtered(lambda r: not r.electrical_device_line_ids)
            if empty_requests:
                names = ", ".join(empty_requests.mapped('name'))
                raise UserError(_(
                    "Cannot create invoice: the following requests have no electrical device lines:\n%s\n"
                    "All selected requests must contain at least one device line."
                ) % names)

            for rec in self:
                line_ids = []
                for line in rec.electrical_device_line_ids:
                    invoice_line_vals = {
                        'name': rec.name or _('Electrical Device Line'),
                        'product_id': line.product_id.id or False,
                        'account_id': line.device_id.account_id.id or False,
                        'analytic_account_id': (
                            rec.family_id.branch_family_id.branch.analytic_account_id.id
                            if rec.family_id.branch_family_id
                               and rec.family_id.branch_family_id.branch
                               and rec.family_id.branch_family_id.branch.analytic_account_id
                            else False
                        ),
                        'quantity': line.quantity,
                        'price_unit': line.unit_price,
                        'benefit_family_id': rec.family_id.id,
                    }
                    line_ids.append((0, 0, invoice_line_vals))

                if not line_ids:
                    raise UserError(_("No invoice lines could be created."))
                vendor_bill = self.env['account.move'].create({
                    'move_type': 'in_invoice',
                    'partner_id': rec.service_producer_id.id,
                    'partner_shipping_id': rec.family_id.partner_id.id,
                    'journal_id': validation_setting.journal_id.id,
                    # 'accountant_id': self.accountant_id.id,
                    'invoice_line_ids': line_ids,
                    'ref': rec.name or False,
                })
                rec.vendor_bill = vendor_bill

    def _get_total_move_lines(self):
        for rec in self:
            if self.service_cat.payment_method == "payment_order":
                moves = rec.payment_order_ids.mapped('move_id')
            elif self.service_cat.payment_method == "invoice":
                moves = self.vendor_bill

            rec.total_moves = len(moves)

    def action_open_related_move_records(self):
        if self.service_cat.payment_method == "payment_order":
            moves = self.payment_order_ids.mapped('move_id')
        elif self.service_cat.payment_method == "invoice":
            moves = self.vendor_bill

        return {
            'name': _('Vendor Bills'),
            'type': 'ir.actions.act_window',
            'res_model': 'account.move',
            'view_mode': 'tree,form',
            'domain': [('id', 'in', moves.ids)],
        }

    def action_open_payment_orders(self):
        self.ensure_one()
        if not self.payment_order_ids:
            raise UserError(_("No payment orders are linked to this request."))

        return {
            'name': _('Payment Orders'),
            'type': 'ir.actions.act_window',
            'res_model': 'payment.orders',
            'view_mode': 'tree,form',
            'domain': [('id', 'in', self.payment_order_ids.ids)],
            'context': {'create': False},
        }

    @api.depends('family_id', 'service_type', 'service_cat')
    def _get_estimated_rent_amount(self):
        for rec in self:
            rec.estimated_rent_amount = 0.0

            if not rec.family_id:
                continue
            if rec.service_type == 'rent':
                for item in rec.service_cat.rent_lines:
                    if rec.family_id.benefit_category_id != item.benefit_category_id or rec.family_id.benefit_member_count != item.benefit_count:
                        continue

                    # Determine rent amount based on branch type and property type
                    branch_type = rec.family_id.branch_family_id.branch_type
                    is_shared_rent = (
                            rec.family_id.property_type_id and
                            rec.family_id.property_type_id.type == 'rent' and
                            rec.family_id.property_type_id.is_shared
                    )
                    discount = item.discount_rate_shared_housing / 100.0 if is_shared_rent else 1
                    if branch_type == 'branches':
                        rec.estimated_rent_amount = item.estimated_rent_branches * discount
                    elif branch_type == 'governorates':
                        rec.estimated_rent_amount = item.estimated_rent_governorate * discount
            if rec.service_type == 'alternative_housing':
                for item in rec.rent_for_alternative_housing.rent_lines:
                    # Check if benefit category and member count match
                    if rec.family_id.benefit_category_id != item.benefit_category_id or rec.family_id.benefit_member_count != item.benefit_count:
                        continue

                    # Determine rent amount based on branch type and property type
                    branch_type = rec.family_id.branch_custom_id.branch_type
                    is_shared_rent = (
                            rec.family_id.property_type_id and
                            rec.family_id.property_type_id.type == 'rent' and
                            rec.family_id.property_type_id.is_shared
                    )

                    if branch_type == 'branches':
                        rec.estimated_rent_amount = item.estimated_rent_branches * (
                            item.discount_rate_shared_housing if is_shared_rent else 1)
                    elif branch_type == 'governorates':
                        rec.estimated_rent_amount = item.estimated_rent_governorate * (
                            item.discount_rate_shared_housing if is_shared_rent else 1)

    @api.depends('estimated_rent_amount', 'payment_type')
    def _get_estimated_rent_amount_payment(self):
        for rec in self:
            rec.estimated_rent_amount_payment = rec.estimated_rent_amount
            if rec.estimated_rent_amount and rec.payment_type:
                rec.estimated_rent_amount_payment = rec.estimated_rent_amount / int(rec.payment_type)

    @api.depends('rent_amount', 'payment_type')
    def _get_rent_amount_payment(self):
        for rec in self:
            if rec.rent_amount and rec.payment_type:
                rec.rent_amount_payment = rec.rent_amount * 12 / int(rec.payment_type)
            else:
                rec.rent_amount_payment = 0.0

    @api.depends('family_id', 'service_cat', 'payment_type')
    def _get_added_amount_if_mother_dead(self):
        for rec in self:
            added_amount_if_mother_dead = 0.0
            if rec.family_id.mother_marital_conf.is_dead:
                added_amount_if_mother_dead = rec.service_cat.raise_amount_for_orphan
                if rec.service_cat.raise_amount_for_orphan and rec.payment_type:
                    added_amount_if_mother_dead = rec.service_cat.raise_amount_for_orphan / int(rec.payment_type)
            rec.added_amount_if_mother_dead = added_amount_if_mother_dead
