#!/usr/bin/env python3
# turismo_data.py

"""Tratamiento de datos de turismo para django"""

import logging
import sys
import pathlib
import time
from datetime import datetime
from dateutil.relativedelta import relativedelta
#from urllib import request
import pandas as pd
import numpy as np
import sqlite3

'''
import matplotlib.pyplot as plt
#import matplotlib.gridspec as gridspec

# Regressions
from scipy import signal
from statsmodels.tsa.stattools import bds, acf, pacf
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.stattools import adfuller  # Dickey Fuller aumenado
import statsmodels.api as sm

'''

logging.basicConfig(
    format="%(asctime)s %(levelname)s:%(name)s: %(message)s",
    level=logging.DEBUG,
    datefmt="%H:%M:%S",
    stream=sys.stderr,
)
logger = logging.getLogger(__name__)


def calendario (fecha = datetime.now(), local_log = False):
       
    '''
    Return Salida[](string):
    
    0 - Fecha de entrada
    1 - YYYY-MM-DD HH:MM
    2 - Fecha DD-MM-YYYY
    3 - Fecha YYYY-MM-DD
    4 - Año
    5 - Mes
    6 - Mes - nombre
    7 - AÑO-MES
    8 - Día
    8 - Día de la semana  - número 1..7
    10 - Día - nombre
    11 - Día del año
    12 - Días del año
    13 - Hora
    14 - Minuto
    15 - Trimestre
    16 - AÑO-TRIMESTRE
    17 - Semana
    18 - AÑO-SEMANA
           
    '''
    
    logger = logging.getLogger('&calendario')
    logger.disabled = local_log
    
    salida = [0]*20
    
    try:
       
       nombre_mes = ['ENE', 'FEB', 'MAR', 'ABR','MAY','JUN', 'JUL', 'AGO', 'SEP', 'OCT', 'NOV', 'DIC']
       nombre_dia = ['L', 'M', 'X', 'J', 'V', 'S', 'D']
       trimestre = ['01','01','01','02','02','02','03','03','03','04','04','04']
        
       logger.info('Date in: ' + str(fecha))
       
       
       fhm = datetime.strftime(fecha,'%Y-%m-%d %H:%M')
       f = datetime.strftime(fecha,'%d-%m-%Y')
       fr = datetime.strftime(fecha,'%Y-%m-%d')
       y = datetime.strftime(fecha,'%Y')
       m = datetime.strftime(fecha,'%m')
       d = datetime.strftime(fecha,'%d')
       ds= datetime.strftime(fecha,'%u') # Iso 8601(1..7)
       mn = nombre_mes[int(m)-1]
       dn = nombre_dia[int(ds)-1]
       dy= datetime.strftime(fecha,'%j')
       hora = datetime.strftime(fecha,'%H')
       minuto = datetime.strftime(fecha,'%M')
       # Iso 8601 La semana 01 es la que contiene el 4 de enero
       semana = datetime.strftime(fecha,'%V') 
       # Iso 8601 lunes primer dia de la semana
       ym = datetime.strftime(fecha,'%YM%m')
       q = trimestre[int(m)-1]
       yq = datetime.strftime(fecha,'%YQ')+ q
       yw = datetime.strftime(fecha,'%YW%V')
       try:
            febrero29 = datetime.fromisoformat(y +'-02-29')
            bisiesto = datetime.strftime(febrero29, '%b')
            # Si no es bisiesto da error y se va a la excepción
            diasanyo = str(366)
       except:
            diasanyo = str(365)
       

       salida = [fecha, fhm, f, fr,y, m, mn, ym, d, ds, dn, dy, diasanyo, hora, minuto, q, yq, semana, yw]
       
       
       logger.info('Fecha H:M: ' + fhm)
       logger.info('Fecha D-M-Y: ' + f)
       logger.info('Fecha Y-M-D: ' + fr)
       logger.info('Año: ' + y)
       logger.info('Mes: ' + m)
       logger.info('Mes (nombre): ' + mn)
       logger.info('Año-Mes: ' + ym)
       logger.info('Dia: ' + d)
       logger.info('Día Semana: ' + ds)
       logger.info('Día Semana (nombre): ' + dn)
       logger.info('Día del Año: ' + dy)
       logger.info('Días del Año: ' + diasanyo)
       logger.info('Semana: ' + hora)
       logger.info('Minuto: ' + minuto)
       logger.info('Trimestre: ' + q)
       logger.info('Año-Trimestre: ' + yq)
       logger.info('Semana: ' + semana)
       logger.info('Año-Semana: ' + yw)
       
       logger.info('Nº datos: ' + str(len(salida)))
             
       return salida
       
    except:  # catch *all* exceptions
        logging.exception('Error: [{}]'.format(sys.exc_info()))
        return salida



def transform_file_df (local_log, f): # Fun: Fichero a dataframe
    '''
    Transform file to dataframe
    
    Parameters:
    ----------                                                                                       
        local_log: False activa el logging
        f: fichero de entrada
    Return:
    ----------
        df: dataframe datos del fichero
    '''
    logger = logging.getLogger('&transform_file_df')
    logger.disabled = local_log
    try:
        
       logger.info('File in: ' + f) 
       df = pd.read_excel(f, header=0)
       logger.info('Return: df-> len: {}, type: {}'.format(len(df), type(df)))
       logger.info(df.describe())
       
       return df
       
    except:  # catch *all* exceptions
        logging.exception('Error: [{}]'.format(sys.exc_info())) 


def transform_filter_cat (local_log, df, cod, n_last): # Fun: Filtra por categoria
    '''
    Filtra el dataframe por categoria
    
    Parameters:
    ----------                                                                                         
        local_log: False activa el logging
        df: dataframe con los datos de todas las categorías
        cod: codigo de la categoria a filtrar
        n_last: filtramos los n ultimos meses
    return:
    ----------
        xy : diccionario con PERIDO - VALOR
        x : PERIDO
        y : VALOR
        y_12 : VALOR en el 12 periodos antes
        y_var12 : % de variación respecto al mismo periodo del año anterior
        
    '''
    logger = logging.getLogger('&transform_filter_cat')
    logger.disabled = local_log
    
    try:
        
       logger.info('df in: ') 
       df1 = df.loc[df['COD'] == cod]
       df2 = df1[['FECHA', 'VALOR', 'COD', 'CATEGORIA']]
       df2.set_index('FECHA', inplace=True)
       df2 = df2.sort_values('FECHA')
       # Coluna añadida con valores retrasados 12 meses
       df2['VALOR_12'] = df2['VALOR'].shift(12)
       df2['VALOR_VAR12'] = round((df2['VALOR']-df2['VALOR_12'])*100/df2['VALOR_12'],2)
       df2['PERIODO'] = pd.to_datetime(df2.index)
       df2['PERIODO'] = df2['PERIODO'].apply(lambda x: calendario(x)[7])
       df2.replace([np.inf, -np.inf], 0, inplace = True)
       df2 = df2.tail(n_last) # Ultimos n meses
       #print(df2)
       x = df2['PERIODO'].tolist()  # Valores de x
       y = df2['VALOR'].tolist()  # Valores de y
       y_12 = df2['VALOR_12'].tolist()  # Valores de y retardado 12 meses
       y_var12 = df2['VALOR_VAR12'].tolist()  # Valores de variacion respecto año anterior
       df0 = df2[['VALOR']]
       df0_lag12 = df2[['VALOR_12']]
       df0_var12 = df2[['VALOR_VAR12']]
       xy = dict(df2[['PERIODO', 'VALOR']].values)
       logger.info('Return: df0 -> len: {}, type: {}'.format(len(df0), type(df0)))
       logger.info(df2.describe())
       logger.info(df2.dtypes)
       
       salida = [xy, x, y, y_12, y_var12]
       
       
       return salida
       
    except:  # catch *all* exceptions
        logging.exception('Error: [{}]'.format(sys.exc_info()))
        return salida # devolverá todo ceros si hay excepción 
    



def turismo_bd_categoria (bd = '/home/ja/Documentos/test/lartica/db.sqlite3'):
    
    logger = logging.getLogger('__' + sys._getframe().f_code.co_name)
    logger.disabled = False
    
    try: 
        logger.info('BD - Categorias')
        
        ''' BD '''
        con = sqlite3.connect(bd) # Conexión
        cur = con.cursor() # Cursor
        consulta = 'SELECT DISTINCT COD, CATEGORIA FROM TurismoCategoria;'
        df = pd.read_sql_query(consulta, con)
        con.close() # Cierre de conexion
        ''' BD '''
      
        cod_cat = dict(df.values)
        cod = df['COD'].tolist()  # Valores de COD
        categoria = df['CATEGORIA'].tolist()  # Valores de CATEGORIA
        salida = [cod_cat, cod, categoria]
        
        return salida
        
    except:  # catch *all* exceptions
        logger.exception('Error: [{}]'.format(sys.exc_info()))
    

def turismo_bd_datos (bd = '/home/ja/Documentos/test/lartica/db.sqlite3', codigo= 'EOT9', n_ultimos = 25):
    
    logger = logging.getLogger('__' + sys._getframe().f_code.co_name)
    logger.disabled = False
    
    try: 
        logger.info('BD - Datos')
        
        ''' BD '''
        con = sqlite3.connect(bd) # Conexión
        cur = con.cursor() # Cursor
        #for row in cur.execute('SELECT * FROM TURISMO_00;'): print(row)
        consulta_datos = 'SELECT {} FROM Turismo WHERE COD = "{}" ORDER BY "FECHA" DESC LIMIT {};'.format ('*', codigo, n_ultimos)
        df = pd.read_sql_query(consulta_datos, con)
        con.close() # Cierre de conexion
        ''' BD '''
        
        '''
        print(df_categoria.dtypes)
        print(df_categoria.describe())
        print(df.dtypes)
        print(df.describe())
        '''
        df = df.sort_values(by = ['PERIODO'], ascending = [True])
        df.replace([np.inf, -np.inf,'',np.nan], 0, inplace = True)
        print(df)
        xy = dict(df[['PERIODO', 'VALOR']].values)
        x = df['PERIODO'].tolist()  # Valores de x
        y = df['VALOR'].tolist()  # Valores de y
        y_12 = df['VALOR_12'].tolist()  # Valores de y retardado 12 meses
        y_var12 = df['VALOR_VAR12'].tolist()  # Valores de variacion respecto año anterior
        xy = dict(df[['PERIODO', 'VALOR']].values)
        salida = [xy, x, y, y_12, y_var12]
        
        return salida
        
    except:  # catch *all* exceptions
        logger.exception('Error: [{}]'.format(sys.exc_info()))
    


def main (local_log, periodos, f): # Fun: Main 
     
    '''
    Parameters
    ----------
    local_log : TYPE: Boolean, False - activa el logging

    Returns
    -------
    None.

    '''

    try:
       ''' 
       df = transform_file_df(local_log, f)
       cod = 'EOT1'
       data = transform_filter_cat (local_log, df, cod, periodos)
       '''
       categorias = turismo_bd_categoria()
       data = turismo_bd_datos (codigo = 'EOT1619')
       print(data[4])
       return data

    except:  # catch *all* exceptions
        logging.exception('Error: [{}]'.format(sys.exc_info()))    
    

if __name__ == "__main__": # Main
    start = time.perf_counter()
    assert sys.version_info >= (3, 7),"Script requires Python 3.7+."
    here = pathlib.Path(__file__).parent
    logger.disabled = False
    logger.info(here)
    logger.info('Initium novum')
    # ********** INICIO **********
    
    local_log_disabled = False # False activa el logging
    main(local_log_disabled, 25, 'd_turismo.xlsx')
    '''
    now = datetime.now()
    cal = calendario (now, local_log_disabled)
    print (cal[1:5])
    print (cal)
    '''
    
    # ********** FIN **********
    logger.info('Ave verum')
    elapsed = time.perf_counter() - start
    logger.info(f"Program completed in {elapsed:0.5f} seconds.")

