#!/usr/bin/env python3

import falcon
from middleware import get_template
from urllib.parse import unquote


class AppEmpresas(object):
    template = 'empresas.html'

    def __init__(self, db):
        self._db = db

    @falcon.after(get_template)
    def on_get(self, req, resp):
        values = req.params
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        opt = values.pop('opt', '1')
        if opt == '1':
            req.context['result'] = self._db.empresa_agregar(values)
        elif opt == '2':
            req.context['result'] = self._db.respaldar_dbs()
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.empresa_borrar(values):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppLogin(object):
    template = 'login.html'

    def __init__(self, db):
        self._db = db

    @falcon.after(get_template)
    def on_get(self, req, resp):
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        session = req.env['beaker.session']
        session.invalidate()
        values = req.params
        values['rfc'] = values['rfc'].upper()
        values['ip'] = req.remote_addr
        result, user = self._db.authenticate(values)
        if result['login']:
            session.save()
            session['userobj'] = user
            session['user'] = result['user']
            session['rfc'] = values['rfc']
        req.context['result'] = result
        resp.status = falcon.HTTP_200


class AppLogout(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        session = req.env['beaker.session']
        session.delete()
        resp.status = falcon.HTTP_200
        raise falcon.HTTPTemporaryRedirect('/')


class AppAdmin(object):
    template = 'admin.html'

    def __init__(self, db):
        self._db = db

    @falcon.after(get_template)
    def on_get(self, req, resp):
        resp.status = falcon.HTTP_200


class AppMain(object):
    template = 'main.html'

    def __init__(self, db):
        self._db = db

    @falcon.after(get_template)
    def on_get(self, req, resp):
        resp.status = falcon.HTTP_200


class AppValues(object):
    TABLES = ('allusuarios', 'usuario', 'usuarioupdate', 'editusuario',
            'addusuario')

    def __init__(self, db):
        self._db = db

    def _valid_user(self, table, user):
        if table in self.TABLES:
            if user.es_admin or user.es_superusuario:
                return True
            else:
                return False

        return True

    def on_get(self, req, resp, table):
        values = req.params
        session = req.env['beaker.session']

        if table == 'product':
            original = values['name']
            try:
                values['name'] = unquote(req.query_string.split('=')[1])
            except Exception as e:
                values['name'] = original

        if req.path in ('/values/titlelogin', '/values/empresas'):
            req.context['result'] = self._db.get_values(table, values, session)
            resp.status = falcon.HTTP_200
            return

        if not 'userobj' in session and req.path != '/values/empresas':
            session.invalidate()
            raise falcon.HTTPTemporaryRedirect('/')

        if table == 'admin':
            req.context['result'] = session['userobj'].es_superusuario \
                or session['userobj'].es_admin
        else:
            if not self._valid_user(table, session['userobj']):
                resp.status = falcon.HTTP_403
                return

            req.context['result'] = self._db.get_values(table, values, session)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp, table):
        values = req.params
        session = req.env['beaker.session']

        if table == 'usuario' and (session['userobj'].id == int(values['id'])):
            resp.status = falcon.HTTP_204
            return

        if not self._valid_user(table, session['userobj']):
            resp.status = falcon.HTTP_403
            return

        if self._db.delete(table, values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204

    def on_post(self, req, resp, table):
        file_object = req.get_param('upload')
        if file_object is None:
            session = req.env['beaker.session']
            values = req.params

            if not self._valid_user(table, session['userobj']):
                resp.status = falcon.HTTP_403
                return

            if table == 'correo':
                req.context['result'] = self._db.validate_email(values)
            elif table == 'sendmail':
                req.context['result'] = self._db.send_email(values, session)
            elif table == 'enviarprefac':
                req.context['result'] = self._db.enviar_prefac(values)
            elif table == 'addmoneda':
                req.context['result'] = self._db.add_moneda(values)
            elif table == 'addunidad':
                req.context['result'] = self._db.add_unidad(values)
            elif table == 'addimpuesto':
                req.context['result'] = self._db.add_impuesto(values)
            elif table == 'addusuario':
                req.context['result'] = self._db.add_usuario(values)
            elif table == 'editusuario':
                req.context['result'] = self._db.edit_usuario(values)
            elif table == 'bdfl':
                req.context['result'] = self._db.importar_bdfl()
            elif table == 'invoicenotes':
                req.context['result'] = self._db.save_invoice_notes(values)
            elif table == 'nivedu':
                req.context['result'] = self._db.add_nivel_educativo(values)
            else:
                req.context['result'] = self._db.validate_cert(values, session)
        else:
            req.context['result'] = self._db.add_cert(file_object)
        resp.status = falcon.HTTP_200


class AppFiles(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp, table):
        values = req.params
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp, table):
        session = req.env['beaker.session']
        file_object = req.get_param('upload')
        req.context['result'] = self._db.upload_file(session, table, file_object)
        resp.status = falcon.HTTP_200


class AppConfig(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.get_config(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.add_config(values)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.delete('config', values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppPartners(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.get_partners(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.partner(values)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.delete('partner', values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppStudents(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.get_students(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.students(values)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.delete('students', values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppProducts(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']

        if 'opt' in values:
            req.context['result'] = self._db.products_get(values, user)
        else:
            req.context['result'] = self._db.get_products(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.products(values)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.delete('product', values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppInvoices(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        session = req.env['beaker.session']
        req.context['result'] = self._db.get_invoices(values, session['userobj'])
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        session = req.env['beaker.session']
        req.context['result'] = self._db.invoice(values, session['userobj'])
        resp.status = falcon.HTTP_200

    def on_put(self, req, resp):
        values = req.params
        session = req.env['beaker.session']
        req.context['result'] = self._db.invoice_put(values, session['userobj'])
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        session = req.env['beaker.session']
        if self._db.delete('invoice', values['id'], session['userobj']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppPreInvoices(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.get_preinvoices(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.preinvoice(values)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.delete('preinvoice', values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppTickets(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        session = req.env['beaker.session']
        req.context['result'] = self._db.get_tickets(values, session['userobj'])
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        session = req.env['beaker.session']
        req.context['result'] = self._db.tickets(values, session['userobj'])
        resp.status = falcon.HTTP_200


class AppEmisor(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        session = req.env['beaker.session']
        req.context['result'] = self._db.get_emisor(session['rfc'])
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.emisor(values)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.delete('invoice', values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppCuentasBanco(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        session = req.env['beaker.session']
        req.context['result'] = self._db.get_cuentasbanco(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.cuentasbanco(values)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.delete('cuentasbanco', values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppMovimientosBanco(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        session = req.env['beaker.session']
        req.context['result'] = self._db.get_movimientosbanco(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        # ~ req.context['result'] = self._db.add_movbanco(values)
        req.context['result'] = self._db.bankmovement(values)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.delete('movbanco', values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppFolios(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.get_folios()
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.add_folios(values)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.delete('folios', values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppEmployees(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.get_employees(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.employees(values)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.delete('employee', values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppNomina(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        if 'opt' in values:
            req.context['result'] = self._db.nomina_get(values, user)
        else:
            by = values.get('by', '')
            req.context['result'] = self._db.get_nomina(values)
            if 'download' in by:
                name = req.context['result']['name']
                req.context['blob'] = req.context['result']['data']
                resp.content_type = 'application/octet-stream'
                resp.append_header(
                    'Content-Disposition', f'attachment; filename={name}')
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        session = req.env['beaker.session']
        req.context['result'] = self._db.nomina(values, session['userobj'])
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.delete('nomina', values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppDocumentos(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp, type_doc, id_doc):
        # ~ print('TD', type_doc)
        session = req.env['beaker.session']
        req.context['result'], file_name, content_type = \
            self._db.get_doc(type_doc, id_doc, session['rfc'])
        if not type_doc in ('pdf', 'pre', 'tpdf', 'pdfpago', 'html', 'nompdf'):
            resp.append_header('Content-Disposition',
                'attachment; filename={}'.format(file_name))
        if type_doc in ('pdf', 'nompdf', 'pdfpago'):
            resp.append_header('Content-Disposition',
                    'inline; filename={}'.format(file_name))
        resp.content_type = content_type
        resp.status = falcon.HTTP_200


# ~ Revisado
class AppInvoicePay(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.get_invoicepay(values)
        resp.status = falcon.HTTP_200


class AppCfdiPay(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.get_cfdipay(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.cfdipay(values)
        resp.status = falcon.HTTP_200


class AppSATBancos(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.get_sat_bancos(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.sat_bancos(values)
        resp.status = falcon.HTTP_200


class AppSATFormaPago(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.get_sat_forma_pago(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.sat_forma_pago(values)
        resp.status = falcon.HTTP_200


class AppSATLeyendaFiscales(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.sat_leyendas_fiscales_get(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.sat_leyendas_fiscales_post(values)
        resp.status = falcon.HTTP_200

    def on_delete(self, req, resp):
        values = req.params
        if self._db.sat_leyendas_fiscales_delete(values['id']):
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_204


class AppSociosCuentasBanco(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.get_partners_accounts_bank(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.partners_accounts_bank(values)
        resp.status = falcon.HTTP_200


class AppCert(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.cert_get(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.cert_post(values)
        resp.status = falcon.HTTP_200


class AppSucursales(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.sucursales_get(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.sucursales_post(values)
        resp.status = falcon.HTTP_200


class AppPartnerProducts(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.partner_products_get(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        req.context['result'] = self._db.partner_products_post(values)
        resp.status = falcon.HTTP_200


class AppInventoryEntries(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.inventory_entries_get(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        req.context['result'] = self._db.inventory_entries_post(values, user)
        resp.status = falcon.HTTP_200


class AppWareHouse(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        req.context['result'] = self._db.warehouse_get(values)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        req.context['result'] = self._db.warehouse_post(values, user)
        resp.status = falcon.HTTP_200


class AppWareHouseProduct(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        req.context['result'] = self._db.warehouseproduct_get(values, user)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        req.context['result'] = self._db.warehouseproduct_post(values, user)
        resp.status = falcon.HTTP_200


class AppTicketsDetails(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        req.context['result'] = self._db.ticketsdetails_get(values, user)
        resp.status = falcon.HTTP_200


class AppUsers(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        req.context['result'] = self._db.users_get(values, user)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        req.context['result'] = self._db.users_post(values, user)
        resp.status = falcon.HTTP_200


class AppSATUnidadesPeso(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        req.context['result'] = self._db.sat_unidades_peso_get(values, user)
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        req.context['result'] = self._db.sat_unidades_peso_post(values, user)
        resp.status = falcon.HTTP_200


class AppSATRegimenes(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        req.context['result'] = self._db.sat_regimenes_get(values, user)
        resp.status = falcon.HTTP_200


class AppSociosRegimenes(object):

    def __init__(self, db):
        self._db = db

    def on_get(self, req, resp):
        values = req.params
        user = req.env['beaker.session']['userobj']
        req.context['result'] = self._db.socios_regimenes_get(values, user)
        resp.status = falcon.HTTP_200
