# -*- coding: utf-8 -*-

from ..TaqnyatSms import client, make_http_response
from odoo import models, fields, api, _
from datetime import datetime, date
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
from dateutil.relativedelta import relativedelta as rd
from odoo.osv import expression
from odoo.exceptions import UserError, ValidationError, Warning

import re
import logging

_logger = logging.getLogger(__name__)
SAUDI_MOBILE_PATTERN = "(^(05|5)(5|0|3|6|4|9|1|8|7)([0-9]{7})$)"


class Partner(models.Model):
    _inherit = 'res.partner'

    def get_default_country(self):
        country = self.env["res.country"].search([('code','=','SA')],limit=1)
        return country.id
    def get_default_state(self):
        country = self.env["res.country.state"].search([('code','=','001')],limit=1)
        return country.id

    @api.model
    def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
        if not args:
            args = []

            # Extend the domain filter with custom search conditions
        if name and hasattr(self, 'identification_number') and 'identification_number' in self._fields:
            args = expression.OR([args, [('identification_number', operator, name)]])

        return super(Partner, self)._name_search(name, args, operator, limit, name_get_uid)

    account_type = fields.Selection(
        string='',
        selection=[('family', 'Family'),
                   ('sponsor', 'sponsor'),
                   ('benefit', 'Benefit'),
                   ('member', 'Member'),
                   ('vendor', 'Vendor'),
                   ('donor', 'Donor')],
        required=False, )
    is_family = fields.Boolean()
    is_sponsor_portal = fields.Boolean(string='Is Sponsor')
    is_benefit = fields.Boolean()
    is_vendor = fields.Boolean()
    is_donor = fields.Boolean()
    code = fields.Char(string="Code", copy=False)
    sponsor_title = fields.Many2one('res.partner.title',string='Title')
    suffix_title_id = fields.Many2one('res.partner.title',string='Suffix Title')
    company_type = fields.Selection(selection_add=[('charity', _('Charity'))])
    first_name = fields.Char(string="First Name", tracking=True)
    second_name = fields.Char(string="Second Name", tracking=True)
    middle_name = fields.Char(string="Third Name", tracking=True)
    family_name = fields.Char(string="Family Name", tracking=True)
    father_name = fields.Char(string="Father First Name", tracking=True)
    father_second_name = fields.Char(string="Father Second Name", tracking=True)
    father_third_name = fields.Char(string="Father Third Name", tracking=True)
    father_family_name = fields.Char(string="Father Family Name")
    birth_date = fields.Date()
    age = fields.Integer(string="Age", compute='_compute_get_age_date', store=True)
    iban = fields.Char("IBAN")
    bank_id = fields.Many2one('res.bank')
    id_number = fields.Char(string="Id Number", tracking=True)
    id_expiry = fields.Date(string="Id Expiry Date")
    gender = fields.Selection(selection=[('male', 'Male'), ('female', 'Female')], string="Gender")
    id_number_attach = fields.Binary(string="Id Number Attachment")
    health_status = fields.Selection(string='Health Status', selection=[('healthy', 'Healthy'), ('sick', 'Sick')])
    education_level = fields.Selection(
        string='Educational level',
        selection=[
            ('illiterate', 'Illiterate'),
            ('kindergarten', 'Kindergarten'),
            ('primary', 'Primary'),
            ('middle', 'Middle'),
            ('secondary', 'Secondary'),
            ('university', 'University'),
            ('postgraduate', 'Postgraduate'),
        ])
    education_institution = fields.Char()
    country_id = fields.Many2one('res.country',default=get_default_country)
    state_id = fields.Many2one('res.country.state',default=get_default_state)
    city_id = fields.Many2one('res.country.city',domain=[('state_id.code','=','001')])
    marital_status = fields.Selection(
        [('single', _('Single')), ('married', _('Married')), ('widower', _('Widower')), ('divorced', _('Divorced'))],
        _('Marital Status'))
    activation_mode = fields.Selection([
        ('sms', 'SMS'),
        ('email', 'Email')])
    user_type = fields.Selection([
        ('person', 'Person'),
        ('company', 'Company'),
        ('charity', 'Charity'),
    ])

    _sql_constraints = [
        ('mobile_uniq', 'unique (mobile)', 'The Mobile Already Exist!'),
        ('phone_uniq', 'unique (phone)', 'The Phone Already Exist!'),
        ('user_id_uniq', 'unique (user_id)', 'The User Already Exist!'),
    ]


    def get_partner_target_account_type(self, acc_type):
        # Special mappings for account_type -> boolean field names
        special_map = {
            'sponsor': 'is_sponsor_portal',
        }

        # Determine the target boolean field name
        target_field = special_map.get(acc_type, f'is_{acc_type}')

        return target_field

    def set_partner_account_type(self, acc_type):
        self.ensure_one()

        # Determine the target boolean field name
        target_field = self.get_partner_target_account_type(acc_type)

        # Validate that acc_type is one of the selection values and field exists
        valid_types = {key for key, _ in self._fields['account_type'].selection}
        if  target_field in self._fields and (acc_type in valid_types or target_field == 'is_sponsor_portal'):
            update_vals = {target_field: True}
            self.write(update_vals)

    def migrate_account_type_to_booleans(self):
        """
        Server action method to migrate the old `account_type` selection
        to the new `is_<type>` boolean fields for the given recordset.
        """
        records = self.search([])
        _logger.info(f"-> Starting account type migration for {len(records)} partner(s).")
        for partner in records:
            acc_type = partner.account_type
            if not acc_type:
                continue
            partner.set_partner_account_type(acc_type)
        _logger.info("-> Partner account type migration finished.")
        return True

    # Function Get age by birthdate
    @api.depends('birth_date')
    def _compute_get_age_date(self):
        for rec in self:
            if rec.birth_date:
                today = date.today()
                day = datetime.strptime(str(rec.birth_date), DEFAULT_SERVER_DATE_FORMAT)
                age = rd(today, day)
                rec.age = age.years

    # Validate mobile ..
    # @api.constrains('mobile')
    # def check_mobile_value(self):
    #     if self.mobile:
    #         if re.match(SAUDI_MOBILE_PATTERN, self.mobile) == None:
    #             raise ValidationError(
    #                 _('Enter a valid Saudi mobile number'))

    @api.onchange('mobile', 'country_id', 'company_id')
    def _onchange_mobile_validation(self):
        if self.mobile:
            if self.mobile.startswith('+966'):
                mobile = self.mobile[4:]
                self.mobile = mobile
            if re.match(SAUDI_MOBILE_PATTERN, self.mobile) == None:
                raise ValidationError(
                    _('Enter a valid Saudi mobile number'))

    # @api.multi
    def send_sms_notification(self, body=None, phone=None):
        self.ensure_one()

        if not phone:
            phone = self.mobile

        if not all([phone, body]):
            return False

        if re.match(SAUDI_MOBILE_PATTERN, str(phone)) == None:
            return False

        company_id = self.env.user.company_id or self.env['res.company'].sudo().search([('id', '=', 1)])

        if company_id and company_id.use_sms_notification:
            token = company_id.sms_provider_token or ''
            sender = company_id.sms_sender_name or ''
            if token and sender:

                taqnyt = client(token)
                mobile = '966' + str(phone).lstrip('0')

                recipients = [mobile]
                scheduled = ''
                # Sending a SMS for a Notification
                message = taqnyt.sendMsg(body, recipients, sender, scheduled)

                result = make_http_response(message)

                code = int(result['statusCode'])
                total_count = int(result['totalCount'])
                msg = result['message']

                if code == 201 and total_count >= 1:
                    return True
                else:
                    return False
            else:
                return False
        else:
            return False


class PartnerTitle(models.Model):
    _inherit = 'res.partner.title'

    position = fields.Selection([('prefix', 'Prefix'), ('suffix', 'Suffix'),('both','Both')], default='prefix')