# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
import time
from datetime import datetime, timedelta

from odoo import api, models, Command
from odoo.exceptions import UserError, ValidationError
from odoo.tools.misc import file_open
from odoo.addons.account.models.chart_template import template

_logger = logging.getLogger(__name__)


class AccountChartTemplate(models.AbstractModel):
    _inherit = "account.chart.template"

    @api.model
    def _install_demo(self, companies):
        if not isinstance(companies, models.BaseModel):
            companies = self.env['res.company'].browse(companies)
        in_without_state = companies.filtered(lambda c: c.chart_template == "in" and not c.state_id)
        if in_without_state:
            _logger.warning('Error while loading Indian-Accounting demo data in the companies "%s". State is not set in the company.', companies.mapped('name'))
        return super()._install_demo(companies - in_without_state)

    @template(template='in', model='res.company', demo=True)
    def _l10n_in_res_company_demo(self):
        return {
            self.env.company.id: {
                'account_use_credit_limit': True,
                'l10n_in_is_gst_registered': True,
                'l10n_in_tcs_feature': True,
                'l10n_in_tds_feature': True,
                'l10n_in_edi_production_env': False,
            },
        }

    @template(template='in', model='ir.default', demo=True)
    def _l10n_in_ir_default_demo(self):
        return {
            'sales_credit_limit': {
                'field_id': 'account.field_res_partner__credit_limit',
                'company_id': self.env.company.id,
                'json_value': '10000',
            },
        }

    @template(template='in', model='res.partner.category', demo=True)
    def _l10n_in_res_partner_category_demo(self):
        return {
            'res_partner_category_registered': {
                'name': 'Registered',
                'color': 2,
            },
            'res_partner_category_unregistered': {
                'name': 'Unregistered',
                'color': 3,
            },
        }

    @template(template='in', model='res.partner', demo=True)
    def _l10n_in_res_partner_demo(self):
        company = self.env.company
        inter_state_ref = 'base.state_in_ts'
        intra_state_ref = 'base.state_in_gj'
        default_partner_dict = {'country_id': 'base.in', 'company_id': company.id}
        return {
            'res_partner_registered_customer': {
                **default_partner_dict,
                'name': 'B2B Customer Intra State',
                'category_id': 'res_partner_category_registered',
                'l10n_in_gst_treatment': 'regular',
                'street': '201, Second Floor, IT Tower 4',
                'street2': 'InfoCity Gate - 1, Infocity',
                'city': 'Gandhinagar',
                'state_id': 'base.state_in_gj',
                'zip': '382010',
                'vat': '24AABCT1332L2ZD',
            },
            'res_partner_registered_customer_inter_state': {
                **default_partner_dict,
                'name': 'B2B Customer Inter State',
                'category_id': 'res_partner_category_registered',
                'l10n_in_gst_treatment': 'regular',
                'street': 'floor-1, Maddikunta-Ankanpally Village',
                'street2': 'Post box No 2, NH-65',
                'city': 'Hyderabad',
                'state_id': inter_state_ref,
                'zip': '500014',
                'vat': '36AAACM4154G1ZO',
            },
            'res_partner_unregistered_customer':{
                **default_partner_dict,
                'name': 'B2C Customer Intra State',
                'category_id': 'res_partner_category_unregistered',
                'l10n_in_gst_treatment': 'unregistered',
                'street': 'B105, yogeshwar Tower',
                'state_id': intra_state_ref,
                'city': 'Rajkot',
                'zip': '360001'
            },
            'res_partner_unregistered_customer_inter_state':{
                **default_partner_dict,
                'name': 'B2C Customer Inter State',
                'category_id': 'res_partner_category_unregistered',
                'l10n_in_gst_treatment': 'unregistered',
                'street': '80, Sarojini Devi Road',
                'city': 'Hyderabad',
                'state_id': inter_state_ref,
                'zip': '500003'
            },
            'res_partner_registered_supplier_1': {
                **default_partner_dict,
                'name': 'Supplier',
                'category_id': 'res_partner_category_registered',
                'l10n_in_gst_treatment': 'regular',
                'street': '19, Ground Floor',
                'street2': 'Survey Road,Vadipatti',
                'city': 'Madurai',
                'state_id': 'base.state_in_tn',
                'zip': '625218',
                'vat': '33AACCT6304M1DB',
            },
            'res_partner_registered_supplier_2': {
                **default_partner_dict,
                'name': 'Odoo In Private Limited',
                'category_id': 'res_partner_category_registered',
                'l10n_in_gst_treatment': 'regular',
                'street': '401, Fourth Floor, IT Tower 4',
                'street2': 'InfoCity Gate - 1, Infocity',
                'city': 'Hyderabad',
                'state_id': inter_state_ref,
                'zip': '500014',
                'vat': '36AACCT6304M1ZB',
            },
            'res_partner_overseas': {
                'name': 'Supplier Overseas',
                'l10n_in_gst_treatment': 'overseas',
                'street': '142 Street, Rigas building',
                'street2': 'Survey Road,',
                'city': 'City',
                'zip': '000000',
                'state_id': 'base.state_us_5',
                'country_id': 'base.us',
                'company_id': company.id,
            },
        }

    @template(model='account.move', demo=True)
    def _get_demo_data_move(self, template_code):
        if template_code == "in":
            return {
                # Demo of B2B (business-to-business) Taxable supplies made to other registered person.
                self.company_xmlid('demo_invoice_b2b_1'): {
                    'move_type': 'out_invoice',
                    'partner_id': 'res_partner_registered_customer',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'l10n_in_gst_treatment': 'regular',
                    'journal_id': 'sale',
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.product_product_8',
                            'quantity': 2,
                            'price_unit': 40000.0,
                            'tax_ids': [Command.set(['sgst_sale_28'])],
                        }),
                        Command.create({
                            'product_id': 'product.product_product_9',
                            'quantity': 3,
                            'price_unit': 400.0,
                            'tax_ids': [Command.set(['sgst_sale_28', 'cess_5_plus_1591_sale'])],
                        }),
                        Command.create({
                            'product_id': 'product.product_product_10',
                            'quantity': 4,
                            'price_unit': 300.0,
                            'tax_ids': [Command.set(['sgst_sale_18'])],
                        }),
                    ],
                },
                self.company_xmlid('demo_invoice_b2b_2'): {
                    'move_type': 'out_invoice',
                    'partner_id': 'res_partner_registered_customer_inter_state',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'l10n_in_gst_treatment': 'regular',
                    'journal_id': 'sale',
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.product_product_9',
                            'quantity': 2,
                            'price_unit': 4000.0,
                            'tax_ids': [Command.set(['igst_sale_5'])],
                        }),
                        Command.create({
                            'product_id': 'product.product_product_10',
                            'quantity': 3,
                            'price_unit': 300.0,
                            'tax_ids': [Command.set(['igst_sale_5'])],
                        }),
                    ],
                },
                self.company_xmlid('demo_bill_b2b_1'): {
                    'ref': 'INV/001',
                    'move_type': 'in_invoice',
                    'partner_id': 'res_partner_registered_supplier_2',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.consu_delivery_01',
                            'quantity': 1,
                            'price_unit': 1000.0,
                            'tax_ids': [Command.set(['igst_purchase_18'])],
                        }),
                        Command.create({
                            'product_id': 'product.consu_delivery_03',
                            'quantity': 1,
                            'price_unit': 2000.0,
                            'tax_ids': [Command.set(['igst_purchase_18'])],
                        }),
                    ]
                },
                self.company_xmlid('demo_bill_b2b_2'): {
                    'ref': 'INV/002',
                    'move_type': 'in_invoice',
                    'partner_id': 'res_partner_registered_supplier_2',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.consu_delivery_01',
                            'quantity': 4,
                            'price_unit': 1000.0,
                            'tax_ids': [Command.set(['sgst_purchase_18'])],
                        }),
                        Command.create({
                            'product_id': 'product.consu_delivery_03',
                            'quantity': 3,
                            'price_unit': 2000.0,
                            'tax_ids': [Command.set(['sgst_purchase_18'])],
                        }),
                    ]
                },
                self.company_xmlid('demo_bill_b2b_3'): {
                    'ref': 'INV/003',
                    'move_type': 'in_invoice',
                    'partner_id': 'res_partner_registered_supplier_1',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.consu_delivery_01',
                            'quantity': 2,
                            'price_unit': 1000.0,
                            'tax_ids': [Command.set(['sgst_purchase_18'])],
                        }),
                        Command.create({
                            'product_id': 'product.consu_delivery_03',
                            'quantity': 3,
                            'price_unit': 2000.0,
                            'tax_ids': [Command.set(['sgst_purchase_18'])],
                        }),
                    ]
                },
                self.company_xmlid('demo_invoice_to_extract'): {
                    'move_type': 'in_invoice',
                    'message_main_attachment_id': 'ir_attachment_in_invoice_1',
                },
                self.company_xmlid('demo_invoice_service'): {
                    'ref': 'MYS-91021146',
                    'move_type': 'in_invoice',
                    'partner_id': 'res_partner_registered_supplier_2',
                    'invoice_user_id': False,
                    'invoice_date': datetime.now(),
                    'invoice_line_ids': [
                        Command.create({
                            'name': 'Integrated Managed Infrastructure Service',
                            'quantity': 1,
                            'price_unit': 69132.78,
                            'tax_ids': [Command.set(['sgst_purchase_18'])],
                        }),
                    ],
                    'message_main_attachment_id': 'ir_attachment_in_invoice_2',
                },
                # Demo of IMP(Import) of supplies.
                self.company_xmlid('demo_bill_imp'): {
                    'ref': 'BOE/123',
                    'move_type': 'in_invoice',
                    'partner_id': 'res_partner_overseas',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.product_product_4',
                            'quantity': 30,
                            'price_unit': 9000.0,
                            'tax_ids': [Command.set(['sgst_purchase_18'])],
                        }),
                    ]
                },
                # Demo of cdnr(Credit/ Debit Note for registered business). Create credit note for demo b2b bill.
                self.company_xmlid('demo_bill_cdnr_1'): {
                    'ref': 'CR/001',
                    'move_type': 'in_refund',
                    'partner_id': 'res_partner_registered_supplier_2',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now() - timedelta(days=1),
                    'l10n_in_gst_treatment': 'regular',
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.consu_delivery_01',
                            'quantity': 1,
                            'price_unit': 1000.0,
                            'tax_ids': [Command.set(['sgst_purchase_18'])],
                        }),
                        Command.create({
                            'product_id': 'product.consu_delivery_03',
                            'quantity': 1,
                            'price_unit': 2000.0,
                            'tax_ids': [Command.set(['sgst_purchase_18'])],
                        }),
                    ]
                },
                self.company_xmlid('demo_bill_cdnr_2'): {
                        'ref': '000072',
                        'move_type': 'in_refund',
                        'partner_id': 'res_partner_registered_supplier_1',
                        'invoice_user_id': 'base.user_demo',
                        'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                        'invoice_date': datetime.now(),
                        'l10n_in_gst_treatment': 'regular',
                        'invoice_line_ids': [
                            Command.create({
                                'product_id': 'product.consu_delivery_01',
                                'quantity': 1,
                                'price_unit': 1000.0,
                                'tax_ids': [Command.set(['igst_purchase_18'])],
                            }),
                        ]
                    },
                # Demo of B2CS (business to consumer small) Taxable supplies made to other unregistered Person and below INR 2.5 lakhs invoice value.
                self.company_xmlid('demo_invoice_b2cs'): {
                    'move_type': 'out_invoice',
                    'partner_id': 'res_partner_unregistered_customer_inter_state',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'l10n_in_gst_treatment': 'consumer',
                    'journal_id': 'sale',
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.product_product_16',
                            'quantity': 1,
                            'price_unit': 1500.0,
                            'tax_ids': [Command.set(['igst_sale_18'])],
                        }),
                        Command.create({
                            'product_id': 'product.product_product_20',
                            'quantity': 1,
                            'price_unit': 2300.0,
                            'tax_ids': [Command.set(['igst_sale_18'])],
                        }),
                        Command.create({
                            'product_id': 'product.product_product_22',
                            'quantity': 1,
                            'price_unit': 2600.0,
                            'tax_ids': [Command.set(['igst_sale_18'])],
                        }),
                        Command.create({
                            'product_id': 'product.product_product_24',
                            'quantity': 2,
                            'price_unit': 1655.0,
                            'tax_ids': [Command.set(['igst_sale_5'])],
                        }),
                    ]
                },
                #  Demo of B2CL (business to consumer - Large) Taxable supplies made to other unregistered Person and invoice value is more than INR 2.5 lakhs.
                self.company_xmlid('demo_invoice_b2cl'): {
                    'move_type': 'out_invoice',
                    'partner_id': 'res_partner_unregistered_customer',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'l10n_in_gst_treatment': 'consumer',
                    'journal_id': 'sale',
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.consu_delivery_01',
                            'quantity': 3,
                            'price_unit': 90000.0,
                            'tax_ids': [Command.set(['sgst_sale_18'])],
                        }),
                    ]
                },
                # Demo of EXP(Export) supplies including supplies to SEZ/SEZ Developer or deemed exports.
                self.company_xmlid('demo_invoice_exp'): {
                    'move_type': 'out_invoice',
                    'partner_id': 'base.res_partner_3',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'l10n_in_gst_treatment': 'overseas',
                    'l10n_in_shipping_bill_number': '999704',
                    'l10n_in_shipping_bill_date': time.strftime('%Y-%m-02'),
                    'l10n_in_shipping_port_code_id': 'l10n_in.port_code_inixy1',
                    'journal_id': 'sale',
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.product_product_4',
                            'quantity': 30,
                            'price_unit': 8000.0,
                            'tax_ids': [Command.set(['igst_sale_18_exp'])],
                        }),
                    ]
                },
                # Demo of exempt(Nil Rated, Exempted and Non GST supplies). Set Nill rated and Exempted tax in line.
                self.company_xmlid('demo_invoice_nill'): {
                    'move_type': 'out_invoice',
                    'partner_id': 'res_partner_registered_customer',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'l10n_in_gst_treatment': 'regular',
                    'journal_id': 'sale',
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.product_product_1',
                            'quantity': 2,
                            'price_unit': 25000.0,
                            'tax_ids': [Command.set(['exempt_sale'])],
                        }),
                        Command.create({
                            'product_id': 'product.product_product_5',
                            'quantity': 1,
                            'price_unit': 400.0,
                            'tax_ids': [Command.set(['nil_rated_sale'])],
                        }),
                    ]
                },
                # Demo of cdnr(Credit/ Debit Note for registered person). Create credit note for demo b2b invoice.
                self.company_xmlid('demo_invoice_cdnr_1'): {
                    'move_type': 'out_refund',
                    'partner_id': 'res_partner_registered_customer',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'l10n_in_gst_treatment': 'regular',
                    'reversed_entry_id': 'demo_invoice_b2b_1',
                    'journal_id': 'sale',
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.product_product_8',
                            'quantity': 2,
                            'price_unit': 40000.0,
                            'tax_ids': [Command.set(['sgst_sale_28'])],
                        }),
                        Command.create({
                            'product_id': 'product.product_product_9',
                            'quantity': 3,
                            'price_unit': 400.0,
                            'tax_ids': [Command.set(['sgst_sale_28', 'cess_5_plus_1591_sale'])],
                        }),
                        Command.create({
                            'product_id': 'product.product_product_10',
                            'quantity': 4,
                            'price_unit': 300.0,
                            'tax_ids': [Command.set(['sgst_sale_18'])],
                        }),
                    ]
                },
                self.company_xmlid('demo_invoice_cdnr_2'): {
                    'move_type': 'out_refund',
                    'partner_id': 'res_partner_registered_customer',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'l10n_in_gst_treatment': 'regular',
                    'journal_id': 'sale',
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.consu_delivery_01',
                            'quantity': 1,
                            'price_unit': 1000.0,
                            'tax_ids': [Command.set(['sgst_sale_18'])],
                        }),
                        Command.create({
                            'product_id': 'product.consu_delivery_03',
                            'quantity': 1,
                            'price_unit': 2000.0,
                            'tax_ids': [Command.set(['sgst_sale_18'])],
                        }),
                    ]
                },
                # Demo of cdnr(Credit/ Debit Note for unregistered person). Create credit note for demo b2cl invoice.
                self.company_xmlid('demo_invoice_cdnur'): {
                    'move_type': 'out_refund',
                    'partner_id': 'res_partner_unregistered_customer',
                    'invoice_user_id': 'base.user_demo',
                    'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
                    'invoice_date': datetime.now(),
                    'l10n_in_gst_treatment': 'consumer',
                    'reversed_entry_id': 'demo_invoice_b2cl',
                    'journal_id': 'sale',
                    'invoice_line_ids': [
                        Command.create({
                            'product_id': 'product.consu_delivery_01',
                            'quantity': 3,
                            'price_unit': 90000.0,
                            'tax_ids': [Command.set(['sgst_sale_18'])],
                        }),
                    ]
                },
            }
        return super()._get_demo_data_move(template_code)

    @template(model='account.bank.statement', demo=True)
    def _get_demo_data_statement(self, template_code):
        return {} if template_code == 'in' else super()._get_demo_data_statement(template_code)

    @template(model='ir.attachment', demo=True)
    def _get_demo_data_attachment(self, chart_template):
        if chart_template == "in":
            return {
                'ir_attachment_in_invoice_1': {
                    'type': 'binary',
                    'name': 'in_invoice_demo_1.pdf',
                    'res_model': 'account.move',
                    'res_id': 'demo_invoice_to_extract',
                    'raw': file_open(
                        'l10n_in/static/demo/in_invoice_demo_1.pdf', 'rb'
                    ).read()
                },
                'ir_attachment_in_invoice_2': {
                    'type': 'binary',
                    'name': 'in_invoice_demo_2.pdf',
                    'res_model': 'account.move',
                    'res_id': 'demo_invoice_service',
                    'raw': file_open(
                        'l10n_in/static/demo/in_invoice_demo_2.pdf', 'rb'
                    ).read()
                }
            }
        return super()._get_demo_data_attachment(chart_template)

    @template(model='mail.message', demo=True)
    def _get_demo_data_mail_message(self, chart_template):
        if chart_template == "in":
            return {
                'mail_message_in_invoice_1': {
                    'model': 'account.move',
                    'res_id': 'demo_invoice_to_extract',
                    'body': 'Vendor Bill attachment',
                    'message_type': 'comment',
                    'author_id': 'base.partner_demo',
                    'attachment_ids': [Command.set([
                        'ir_attachment_in_invoice_1',
                    ])]
                },
                'mail_message_in_invoice_2': {
                    'model': 'account.move',
                    'res_id': 'demo_invoice_service',
                    'body': 'Vendor Bill attachment',
                    'message_type': 'comment',
                    'author_id': 'base.partner_demo',
                    'attachment_ids': [Command.set([
                        'ir_attachment_in_invoice_2',
                    ])]
                },
            }
        return super()._get_demo_data_mail_message(chart_template)

    @template(model='mail.activity', demo=True)
    def _get_demo_data_mail_activity(self, template_code):
        return {} if template_code == 'in' else super()._get_demo_data_mail_activity(template_code)

    def _post_load_demo_data(self, template_code):
        if template_code == "in":
            invoices = (
                self.ref('demo_invoice_b2b_1')
                + self.ref('demo_invoice_b2b_2')
                + self.ref('demo_invoice_b2cs')
                + self.ref('demo_invoice_b2cl')
                + self.ref('demo_invoice_exp')
                + self.ref('demo_invoice_nill')
                + self.ref('demo_invoice_cdnr_1')
                + self.ref('demo_invoice_cdnr_2')
                + self.ref('demo_invoice_cdnur')
                + self.ref('demo_bill_b2b_1')
                + self.ref('demo_bill_b2b_2')
                + self.ref('demo_bill_b2b_3')
                + self.ref('demo_bill_imp')
                + self.ref('demo_bill_cdnr_1')
                + self.ref('demo_bill_cdnr_2')
                + self.ref('demo_invoice_service')
            )
            for move in invoices:
                try:
                    move.action_post()
                except (UserError, ValidationError):
                    _logger.exception('Error while posting demo data')
        else:
            super()._post_load_demo_data(template_code)
