from odoo import models, fields, api,_
from odoo.exceptions import UserError, ValidationError,Warning
from psycopg2 import sql, DatabaseError
from datetime import date,datetime

from werkzeug import utils
import base64
import logging
import csv
import base64
import io
import json
import re 
_logger = logging.getLogger(__name__)

# class PaymentTransaction(models.Model):
#     _inherit = 'payment.transaction'

#     donation_ids = fields.Many2many('donation.donation', 'donation_transaction_rel', 'transaction_id', 'donation_id',
#                                       string='Donations', copy=False, readonly=True)

#     def render_donation_button(self, donation, submit_txt=None, render_values=None):
#         values = {
#             'partner_id': donation.partner_id.id,
#             'type': self.type,
#         }
#         if render_values:
#             values.update(render_values)
#         # Not very elegant to do that here but no choice regarding the design.
#         self._log_payment_transaction_sent()
#         return self.acquirer_id.with_context(submit_class='btn btn-primary', submit_txt=submit_txt or _('Pay Now')).sudo().render(
#             self.reference,
#             donation.amount_total,
#             donation.currency_id.id,
#             values=values,
#         )
  
        


class DonationDonation(models.Model):
    _inherit = 'donation.donation'

    invoice_id=fields.Many2one('account.move','invoice')
    transaction_id=fields.Many2one('payment.transaction','payment transaction')
    state_done=fields.Boolean(compute='_compute_donation_state',store=True)
    affectation=fields.Char(compute='_compute_affectation')
    source_import=fields.Char('source import')
    date_import=fields.Date('date import',default=False)
    date_compta=fields.Datetime('date import',default=False)
    # @api.depends('transaction_id.state')
    # def transaction_state(self):
    #     _logger.error("onchange_transaction_state")
    #     if self.state=='done':
    #         if self.donation_ids:
    #             for donation_id in donation_ids:
    #                 _logger.error("donation_id="+str(donation_id))
    #                 donation=request.env['donation.donation'].sudo().search([('id','=',int(donation_id))])
    #                 if donation:donation.state='done'
            
    #         if self.membership_ids:
    #             for membership_id in membership_ids:
    #                 membership=request.env['kalachakra.membership'].sudo().search([('id','=',int(membership_id))])
    #                 if membership:membership.state='done'

    def _compute_affectation(self):
        
        i=1
        for d in self:
            affectation=''
            for line in d.line_ids:
                if i==1:
                    affectation=line.product_id.name
                else:
                     affectation=affectation+ ' ' +line.product_id.name
                i=i+1
            d.affectation=affectation

    @api.depends('invoice_id.payment_state','transaction_id.state')
    def _compute_donation_state(self):
        for d in self:
            if d.invoice_id:
                if d.invoice_id.payment_state=='paid':
                        
                        d.state='done'
                        d.state_done=True
                else:
                        d.state='draft'
                        d.state_done=False
            if d.transaction_id:
                if d.transaction_id.state=='done':
                     if d.state!='done':
                        d.state='done'
                        d.state_done=True
                        d.email_confirmation()
                 

    def email_confirmation(self):
       
       mail_template = self.env['mail.template'].search([('name','=','confirmation_donation')])

       mail_template.email_to = self.partner_id.email

       #mail_template.with_context({'end_date':self.end_date}).send_mail(self.id,False)
       mail_template.send_mail(self.id,False)
        
       return True

    def bulk_remove_draft_donation(self):
        payment_transaction=self.env['payment.transaction'].search([('state','=','draft')])
        if payment_transaction:
            for p in payment_transaction:
                if p.donation_ids:
                    for d in p.donation_ids:
                        #on ne supprime que les dons brouillons
                        if d.state=='draft':
                             today=date.today()
                             b_date = date(d.create_date.year,d.create_date.month, d.create_date.day)
                             #b_date = date(2022,8, 12)
                             e_date = date(today.year,today.month, today.day)
                             diff=e_date-b_date
                           
                             _logger.error("errK2-diff days="+str(diff.days)) 
                             if diff.days>15:self.env['donation.donation'].search([('id','=',int(d.id))]).unlink()

        #on supprime également les dons brouillon de plus de 15 jours non lié à une retraite, donc sans facture
        donation=self.env['donation.donation'].search([('state','=','draft')])
        if donation:
            for d in donation:
                if not d.invoice_id:
                    today=date.today()
                    b_date = date(d.create_date.year,d.create_date.month, d.create_date.day)
                    e_date = date(today.year,today.month, today.day)
                    diff=e_date-b_date
                    _logger.error("errK2-diff days m="+str(diff.days))
                    if diff.days>15:self.env['donation.donation'].search([('id','=',int(d.id))]).unlink()



    def _get_payment_type(self, tokenize=False):
        self.ensure_one()
        return 'form_save' if tokenize else 'form'

    def _create_payment_transaction(self, vals):
        '''Similar to self.env['payment.transaction'].create(vals) but the values are filled with the
        current donation fields (e.g. the partner or the currency).
        :param vals: The values to create a new payment.transaction.
        :return: The newly created payment.transaction record.
        '''
        # Ensure the currencies are the same.
        currency = self[0].currency_id
        # if any(so.pricelist_id.currency_id != currency for so in self):
        #     raise ValidationError(_('A transaction can\'t be linked to sales orders having different currencies.'))

        # Ensure the partner are the same.
        partner = self[0].partner_id
        if any(so.partner_id != partner for so in self):
            raise ValidationError(_('A transaction can\'t be linked to sales orders having different partners.'))

        # Try to retrieve the acquirer. However, fallback to the token's acquirer.
        acquirer_id = vals.get('acquirer_id')
        acquirer = False
        payment_token_id = vals.get('payment_token_id')

        if payment_token_id:
            payment_token = self.env['payment.token'].sudo().browse(payment_token_id)

            # Check payment_token/acquirer matching or take the acquirer from token
            if acquirer_id:
                acquirer = self.env['payment.acquirer'].browse(acquirer_id)
                if payment_token and payment_token.acquirer_id != acquirer:
                    raise ValidationError(_('Invalid token found! Token acquirer %s != %s') % (
                    payment_token.acquirer_id.name, acquirer.name))
                if payment_token and payment_token.partner_id != partner:
                    raise ValidationError(_('Invalid token found! Token partner %s != %s') % (
                    payment_token.partner.name, partner.name))
            else:
                acquirer = payment_token.acquirer_id

        # Check an acquirer is there.
        if not acquirer_id and not acquirer:
            raise ValidationError(_('A payment acquirer is required to create a transaction.'))

        if not acquirer:
            acquirer = self.env['payment.acquirer'].browse(acquirer_id)

        # Check a journal is set on acquirer.
        if not acquirer.journal_id:
            raise ValidationError(_('A journal must be specified for the acquirer %s.', acquirer.name))

        if not acquirer_id and acquirer:
            vals['acquirer_id'] = acquirer.id

        vals.update({
            'amount': sum(self.mapped('amount_total')),
            'currency_id': currency.id,
            'partner_id': partner.id,
            'donation_ids': [(6, 0, self.ids)],
            'type': self[0]._get_payment_type(vals.get('type')=='form_save'),
        })
        
        
        transaction = self.env['payment.transaction'].create(vals)
        
        
        # Process directly if payment_token
        if transaction.payment_token_id:
            transaction.s2s_do_transaction()

        return transaction

    def _import_donation(self):
        files= self.env["opendons.partnerdraftfile"].search([('source_name','=','donation')])
       
        for f in files:
            
            decrypted = base64.b64decode(f.file).decode('utf-8-sig')
            source_name=f.source_name
            

            with io.StringIO(decrypted) as fp:
                reader = csv.DictReader(fp, delimiter=",", quotechar='"')
                for row in reader:

                    vals={}
                    lig_vals={}
                    vals_p={}
                    vals_part={}
                    
                    for key, value in row.items():
                        #on cherche le type de don
                        if key=='Destination don':
                                #dons dans la base:
                                dbdonpdt=['Activités en ligne','Aide à la sangha ordonnée','Autre','Don selon les besoins du centre','Rituels et prières','Soutien aux lamas','Travaux au centre de retraite']
                            #mapping avec les valeur du fichier
                                if value=='Soutien Lamas':
                                    value='Soutien aux lamas'
                                if value=='Soutien Lamas':
                                    value='Soutien aux lamas'
                                if value=='':
                                    value="Autre"
                                donation_product=self.env['product.product'].sudo().search([('name','=',value)],limit=1)
                                if not donation_product:
                                    vals_p={}
                                    vals_p['name']=value
                                    vals_p['donation']=True
                                    vals_p['tax_receipt_ok']=True
                                    vals_p['type']='service'
                                    vals_p['taxes_id']=False
                                    res=self.env['product.product'].create(vals_p)
                                    lig_vals['product_id']=res.id
                                    lig_vals['display_name']=res.display_name
                                    lig_vals['tax_receipt_ok']=res.tax_receipt_ok
                                else:
                                    lig_vals['product_id']=donation_product.id
                                    lig_vals['display_name']=donation_product.display_name
                                    lig_vals['tax_receipt_ok']=donation_product.tax_receipt_ok

                        
                        if key=='Email':
                            vals_part['email']=value.strip()
                            
                            

                        if key=='Nom': vals_part['name']=value.strip()
                        if key=='Prénom':vals_part['firstname']=value.strip()

                        if key=='Date':
                                year_m=value[0:4]
                                month_m=value[5:7]
                                day_m=value[8:10]
                                vals['donation_date']=datetime.strptime(year_m+'-'+month_m+'-'+day_m, '%Y-%m-%d')
                                
                        if key=='Montant':
                            lig_vals['unit_price']=value
                    
                    #création du contact si pas trouvé dans la base
                    partner=self.env['res.partner'].sudo().search([('email','=',vals_part['email'])],limit=1)
                    if not partner:
                        vals_part['origine']='import_don2022'
                        vals_part['tax_receipt_option']='annual'
                        
                        _logger.error(vals_part)

                        new_partner=self.env['res.partner'].create(vals_part)
                        vals['partner_id']=new_partner.id
                    else:
                        vals['partner_id']=partner.id
                    #creation du don avec Chèque comme mode de paiement
                    check_mode=self.env['account.payment.mode'].sudo().search([('name','=','chèque')],limit=1)
                    vals['payment_mode_id']=int(check_mode.id)
                    vals['state']='draft'
                    vals['payment_ref']='import'
                    vals['tax_receipt_option']='annual'
                    vals['source_import']='import dons 2022'
                    vals['date_import']=fields.datetime.now()
                    donation_draft=self.env['donation.donation'].sudo().create(vals)
                    #create line donation
                    lig_vals['donation_id']=donation_draft.id
                    lig_vals['quantity']=1
                    donation_line=self.env['donation.line'].sudo().create(lig_vals)
                    
                    


                        
                        

                   
        return True
    def _cancel_donation(self):
        #annulation des dons créés aujourd'hui
        today=date.today()
        donation=self.env['donation.donation'].search([('create_date','>=',today)])
        for d in donation:
            d.state='cancel'
    
    def fix_donation(self):
        #tax_receipt_total=0 for 	Donation pour favoriser le séjour des personnes à revenu modeste
        donation=self.env['donation.donation'].search([('tax_receipt_total','=',0),('state','=','done')])
        raise UserError(donation)