from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError, Warning
from psycopg2 import sql, DatabaseError
from dateutil.relativedelta import relativedelta
from datetime import datetime
from werkzeug import utils
import json
import logging
_logger = logging.getLogger(__name__)

class EventRegistration(models.Model):
    _inherit = 'event.registration'

    online=fields.Boolean(string='Online participation')
    onthespot_payment=fields.Boolean(string='On the spot payment')
    free_participation=fields.Boolean(related='event_id.free_participation')
    with_membership=fields.Boolean('with membership')
    headphone=fields.Boolean('headphone')
    date_compta=fields.Datetime('date import',default=False)
    date_compta_down_payment=fields.Datetime('date import down payment',default=False)
    date_compta_end_of_stay=fields.Datetime('date import end of stay',default=False)         
    date_payment=fields.Date('date payment',compute='_compute_event_date_payment')
    date_payment_down_payment=fields.Date('date payment down payment',compute='_compute_event_date_payment_down_payment')
    date_payment_balance=fields.Date('date payment balance',compute='_compute_event_date_payment_balance')
    date_payment_end_of_stay=fields.Date('date payment end of stay',compute='_compute_event_date_payment_end_of_stay')
    member_status=fields.Selection(related='partner_id.member_status')
    amount_total=fields.Monetary(related='invoice_id.amount_total')
    def _compute_event_date_payment(self):
         for rec in self:
              if not rec.booking_event:
                   if rec.invoice_id.invoice_payments_widget:
                        payment_info=json.loads(rec.invoice_id.invoice_payments_widget)
                        if payment_info:
                            nb_payments=len(payment_info['content'])
                            _logger.info(payment_info['content'])
                            rec.date_payment= payment_info['content'][nb_payments-1]['date']

                        else:
                            rec.date_payment=False
                   else: rec.date_payment=False
              #booking event
              else:
                   if rec.invoice_id:
                        if rec.invoice_id.invoice_payments_widget:
                            payment_info=json.loads(rec.invoice_id.invoice_payments_widget)
                            if payment_info:
                                rec.date_payment= payment_info['content'][0]['date']
                            else : rec.date_payment=False
                        else :rec.date_payment=False
                        # payments=self.env['account.payment'].search([])
                        # for p in payments:
                        #     if p.reconciled_invoice_ids==rec.invoice_id:
                        #             rec.date_payment=p.date
                        #             break
                   else:
                        rec.date_payment=False
    def _compute_event_date_payment_down_payment(self):
         for rec in self:
              if not rec.booking_event:
                        rec.date_payment_down_payment=False
              else:
                   
                   if rec.down_payment_invoice_id:
                        if rec.down_payment_invoice_id.invoice_payments_widget:
                            payment_info=json.loads(rec.down_payment_invoice_id.invoice_payments_widget)
                            if payment_info:
                                rec.date_payment_down_payment= payment_info['content'][0]['date']
                            else : rec.date_payment_down_payment=False
                        else :rec.date_payment_down_payment=False
                   else:
                        rec.date_payment_down_payment=False
    def _compute_event_date_payment_balance(self):
         for rec in self:
              if not rec.booking_event:
                        rec.date_payment_balance=False
              else:
                   
                   if rec.balance_invoice_id:
                        if rec.balance_invoice_id.invoice_payments_widget:
                            payment_info=json.loads(rec.balance_invoice_id.invoice_payments_widget)
                            if payment_info:
                                rec.date_payment_balance= payment_info['content'][0]['date']
                            else : rec.date_payment_balance=False
                        else :rec.date_payment_balance=False
                   else:
                        rec.date_payment_balance=False
    def _compute_event_date_payment_end_of_stay(self):
         for rec in self:
              if not rec.booking_event:
                        rec.date_payment_end_of_stay=False
              else:
                   
                   if rec.end_of_stay_invoice_id:
                        if rec.end_of_stay_invoice_id.invoice_payments_widget:
                            payment_info=json.loads(rec.end_of_stay_invoice_id.invoice_payments_widget)
                            if payment_info:
                                rec.date_payment_end_of_stay= payment_info['content'][0]['date']
                            else : rec.date_payment_end_of_stay=False
                        else :rec.date_payment_end_of_stay=False
                   else:
                        rec.date_payment_end_of_stay=False

    def action_cancel(self):
        self.write({'state': 'cancel'})
        #annulation des factures non payées
        # if self.invoice_id :
        #     if self.invoice_id.payment_state!='paid':
        #          self.invoice_id.button_draft()
        # if self.down_payment_invoice_id :
        #     if self.down_payment_invoice_id.payment_state!='paid':
        #          self.down_payment_invoice_id.button_draft()
        
        #création d'un avoir pour les factures déjà réglées
        # if self.down_payment_invoice_id :
        #     if self.down_payment_invoice_id.payment_state=='paid':
        #          self.down_payment_invoice_id.button_draft()


    def create(self,vals):

        reg = super(EventRegistration, self).create(vals)
        if reg.event_id.booking_event:
                if reg._check_auto_confirmation():
                        reg.sudo().action_confirm()
                #ajout du questionnaire pour la personne inscrite
                questions=self.env['event.question'].search([('event_id','=',int(reg.event_id))])
                if questions:
                    for question in questions:
                        vals={}
                        vals['sequence']=question.sequence
                        vals['question']=question.question
                        vals['event_registration_id']=reg.id
                        res=self.env['event.registration_questionnaire'].create(vals)
            
                #ajout des options pour la personne inscrite
                # options=self.env['booking.option'].search([('event_id','=',int(reg.event_id))])
                # if options:
                #     for option in options:
                #         vals={}
                #         vals['booking_option_id']=int(option.booking_option_id)
                #         vals['booking_option_price']=option.booking_option_price
                #         vals['event_registration_id']=int(reg.id)
                #         res=self.env['event.registration_option'].create(vals)
        
        #inscription à la newsletter attachée à l'événement
        #si pas une retraite et présence d'une newletter rattaché à l'événement
        if  reg.event_id.recurring_event_newsletter_id:
            mailing_contact=self.env['mailing.contact'].sudo().search([('email','=',reg.partner_id.email)],limit=1)
            #si le contact n'existe pas comme mailing contact, création
            if not mailing_contact:
                vals={}
                vals['email']=reg.partner_id.email
                vals['name']=reg.partner_id.name
                vals['title_id']=int(reg.partner_id.title)
                vals['country_id']=int(reg.partner_id.country_id)
                vals['list_ids']=[(4,int(reg.event_id.recurring_event_newsletter_id))]
                mailing_contact=self.env['mailing.contact'].sudo().create(vals)
            else:
                #si le contact existe, si la liste de diffusion n'est pas lié au contact, on l'ajoute
                if not reg.event_id.recurring_event_newsletter_id in mailing_contact.list_ids:
                    mailing_contact.sudo().write({'list_ids':[(4,int(reg.event_id.recurring_event_newsletter_id))]})

            #inscription à la newsletter générale
            mailing_list=self.env['mailing.list'].sudo().search([('name','=','Newsletter '+self.env.company.name)])
            if mailing_list:
                if not mailing_list in mailing_contact.list_ids:
                        mailing_contact.sudo().write({'list_ids':[(4,int(mailing_list.id))]})
        return reg


    def action_generate_participation_invoice(self,id_registration=None,payment_mode=None,membership=False):
        
        if not id_registration:id_registration=int(self.id)
        reg=self.env['event.registration'].search([('id','=',id_registration)])
        event=self.env['event.event'].search([('id','=',int(reg.event_id))])

        if membership:
             membership_product=self.env['product.product'].search([('membership_product','=',True)],limit=1)
             if not membership_product: raise UserError(_('No membership product, please add one'))

        #Prix à appliquer au produit en fonction du statut de l'inscrit
        status=reg.partner_id.member_status
        
        if status=='not member':product_price=event.participation_standard_price
        if status=='member':product_price=event.participation_member_price
        if status=='super member':product_price=event.participation_super_member_price
        product_id=event.participation_product_id

        
        #création de la facture
        vals={}
        
        vals['partner_id']=int(reg.partner_id)
        vals['invoice_date']=datetime.now()

        #mode de paiement CB
        if payment_mode=='CB':
            electronic_method=self.env['account.payment.method'].search([('code','=','electronic')],limit=1)
            if electronic_method:
                    cb_mode=self.env['account.payment.mode'].search([('payment_method_id','=',int(electronic_method.id))],limit=1)
                    if cb_mode:
                        vals['payment_mode_id']=cb_mode.id
                    else:
                        raise Warning('please configure credit card mode')

        vals['move_type']='out_invoice'
        vals['state']='draft'
        
        invoice=self.env['account.move'].create(vals)
        
        #invoice.state='posted'
        invoice.name='REC'+str(invoice.id)
        invoice.payment_reference=invoice.name
        #creation des écritures comptable
        name=event.participation_product_id.name
        if membership and status=='not member':
            product_price=event.participation_member_price+membership_product.list_price
            name=event.participation_product_id.name+"+"+membership_product.name
        vals={}
        account_credit=self.env['account.account'].search([('code','=','707100')])
        account_debit=self.env['account.account'].search([('code','=','411100')])
        
        vals['move_id']=invoice.id
        vals['product_id']=int(event.participation_product_id)
        vals['quantity']=1
        vals['price_unit']=product_price
        vals['name']=name
        
        vals['account_id']=int(account_credit.id)

        invoice_line=self.env['account.move.line'].with_context(check_move_validity=False).create(vals)
  
        # #debit_line 
        vals_d={}        
        vals_d['move_id']=invoice.id
        vals_d['debit']=product_price
        vals_d['credit']=0
        vals_d['date']=datetime.now()
        vals_d['partner_id']=int(reg.partner_id)
        vals_d['product_id']=int(event.participation_product_id)
        vals_d['name']=name
        vals_d['account_id']=int(account_debit.id)
        vals_d['quantity']=1
        vals_d['price_unit']=product_price
        vals_d['exclude_from_invoice_tab']=True
                    
        invoice_line=self.env['account.move.line'].with_context(check_move_validity=False).create(vals_d)
        l=self.env['account.move.line'].search([('move_id','=',invoice.id),('balance','<',0)])
        l.partner_id=int(reg.partner_id)
        reg.invoice_id=invoice.id
        _logger.error('state invoice='+reg.invoice_id.state)
        #mettre la facture payée si son montant est à zéro
        if product_price==0:reg.invoice_id.state='posted'
        
        return invoice.id

        