package ru.bitel.bgbilling.modules.voice.dyn.mediator.asterisk;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ru.bitel.bgbilling.apps.voice.accounting.mediation.AbstractMediator;
import ru.bitel.bgbilling.apps.voice.accounting.mediation.VoiceRecord;
import ru.bitel.bgbilling.apps.voice.accounting.mediation.VoiceRecordProcessor;
import ru.bitel.common.TimeUtils;
import ru.bitel.common.Utils;

public class AsteriskMediator_v3
    extends AbstractMediator
{
    @Override
    protected VoiceRecord processLine( VoiceRecordProcessor processor, String[] params )
        throws InterruptedException
    {
        CDR cdr = new CDR();
        cdr.amount = Utils.parseInt( params[3], 0 );
        if ( skipCDR( cdr ) )
        {
            return null;
        }
        
        // 0                       1               2       3       4       5      
        // 2024-01-01T00:01:45     32938810        8928    0       C335401 C000000

        VoiceRecord record = processor.next();
        record.sessionStart = TimeUtils.convertLocalDateTimeToDate( LocalDateTime.parse( params[0] ) );        
        record.callingStationId = params[1];
        record.e164CallingStationId = callingStationIdToE164( record.callingStationId );
        record.calledStationId = params[2];
        record.e164CalledStationId = calledStationIdToE164( record.calledStationId );
        record.duration = record.connectionDuration = Utils.parseInt( params[3], 0 );
        record.trunkIncoming = params[4];
        record.trunkOutgoing = params[5];
        record.category = 0;
        
        return record;
    }

    @Override
    protected void parseLog( Path path, Map<String, List<String>> cdrs )
    {
        if ( Files.exists( path ) )
        {
            LocalDateTime now = LocalDateTime.now();
            int defYear = now.getYear() - 2000;
            int defMonth = now.getMonthValue();
            int defDayOfMonth = now.getDayOfMonth();
            int defHour = now.getHour();
            int defMinute = now.getMinute();
            int defSecond = now.getSecond();
            
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHH");
            
            try 
            {
                Files.lines( path ).forEach( line ->
                {
                    try 
                    {
                        getLogger().debug( "line = {}", line );
    
                        // "","9157391874","300#4452802","si",""""" <9157391874>","SIP/MEGAFON-0000f49f","SIP/si2000-0000f4a0","Dial","SIP/si2000/4452802,60","2024-06-09 00:49:23","2024-06-09 00:49:32","2024-06-09 00:50:30",67,58,"ANSWERED","DOCUMENTATION","1717883363.101826",""
                        // Поля
                        //
                        // 0 accountcode: Какой учетный номер используется: account, (строка, 20 символов)
                        // 1 src: Номер Caller*ID (строка, 80 символов)
                        // 2 dst: Расширение направления (строка, 80 символов)
                        // 3 dcontext: Контекст направления (строка, 80 символов)
                        // 4 clid: Caller*ID с текстом (80 символов)
                        // 5 channel: Используемый канал (80 символов)
                        // 6 dstchannel: Канал направления, если подходит (80 символов)
                        // 7 lastapp: Последнее приложение, если подходит (80 символов)
                        // 8 lastdata: Дата последнего приложения (аргументы) (80 символов)
                        // 9 start: Начало вызова (дата/время)
                        // 10 answer: Ответ вызова (дата/время)
                        // 11 end: Конец вызова (дата/время)
                        // 12 duration: Полное время в системе, в секундах (целое), от набора номера до зависания
                        // 13 billsec: Полное время вызова, в секундах (целое), от ответа до зависания
                        // 14 disposition: Что случилось с вызовом: ANSWERED, NO ANSWER, BUSY, FAILED (на некоторых CDR выходных буферах, например ODBC, они могут быть целыми; заметьте, что более детальная инфа может быть найдена в переменной диалплана $HANGUPCAUSE)
                        // 15 amaflags: Какой флаг используется: смотри amaflags: DOCUMENTATION, BILLING, IGNORE и т.д., указанного на базисе каждого канала подобно accountcode.                     
                        
                        List<String> params = parseLine( line );
    
                        CDR cdr = new CDR();
    
                        if ( params.size() < 11 )
                        {
                            return;
                        }
    
                        String ansCode =  params.get( 14 );
    //                  System.out.println( "ansCode = " + params.get( 14 ) );
                        // отбрасывать можно звонки с кодом ответа
                        if ( ansCode.equals( "NO ANSWER" ) || ansCode.equals( "CONGESTION" ) || ansCode.equals( "BUSY" ) )
                        {
                            return;
                        }
                        if ( "anonymous".equals( params.get( 1 ) ) )
                        {
                            return;
                        }
                        
                        // "2024-06-09 00:49:32"
    //                    System.out.println( params.get( 10 ) );
                        int year = Utils.parseInt( params.get( 10 ).substring( 0, 4 ), defYear );
                        int month = Utils.parseInt( params.get( 10 ).substring( 5, 7 ), defMonth );
                        int dayOfMonth = Utils.parseInt( params.get( 10 ).substring( 8, 10 ), defDayOfMonth );
                        int hour = Utils.parseInt( params.get( 10 ).substring( 11, 13 ), defHour );
                        int minute = Utils.parseInt( params.get( 10 ).substring( 14, 16 ), defMinute );
                        int second = Utils.parseInt( params.get( 10 ).substring( 17 ), defSecond );
                        cdr.start = LocalDateTime.of( year, month, dayOfMonth, hour, minute, second );
                        
                        cdr.numberA = callingStationIdToE164( params.get( 1 ) );
                        cdr.origNumberA = params.get( 1 );
    
                        cdr.numberB = calledStationIdToE164( params.get( 2 ) );
                        
                        cdr.trunkIncoming = params.get( 5 );
                        cdr.trunkOutgoing = params.get( 6 );
    
                        cdr.amount = Utils.parseInt( params.get( 13 ), 0 );
                        
                        String date = cdr.start.format( formatter );
                        List<String> buffer = cdrs.get( date );
                        if ( buffer == null )
                        {
                            buffer = new ArrayList<>();
                            cdrs.put( date, buffer );
                        }
                        buffer.add( cdr.toString() );
                        if ( getLogger().isDebugEnabled() )
                        {
                            getLogger().debug( "cdr => {}", cdr.toString() );
                        }
    //                    System.out.println( cdr.toString() );
                    }
                    catch ( Exception ex )
                    {
                        logError( ex );
                    }
                } );
            }
            catch ( Exception ex )
            {
                logError( ex );
            }
        }
    }    
    
    public static void main( String[] args )
    {
        Path rootPath = Paths.get( args[0] );
        Path inboundPath = Paths.get( rootPath.toString(), "inbound" );

        if ( !Files.exists( inboundPath ) || !Files.isDirectory( inboundPath ) )
        {
            System.out.println( inboundPath.toString() + " каталог не найден" );
            System.exit( 1 );
        }
        
        try
        {
            Map<String, List<String>> cdrs = new HashMap<>();
            AsteriskMediator_v3 asteriskMediator_v3 = new AsteriskMediator_v3();
            Files.list( inboundPath ).forEach( f -> asteriskMediator_v3.parseLog( f, cdrs ) );
        }
        catch( Exception ex )
        {
            System.err.println( ex );
            System.exit( 2 );
        }
    }
}
