package ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.impl;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import jakarta.jws.WebMethod;
import jakarta.jws.WebParam;
import jakarta.jws.WebResult;
import jakarta.jws.WebService;
import jakarta.xml.ws.RequestWrapper;
import jakarta.xml.ws.ResponseWrapper;
import ru.bitel.bgbilling.common.BGException;
import ru.bitel.bgbilling.kernel.container.managed.ServerContext;
import ru.bitel.bgbilling.kernel.container.service.server.AbstractService;
import ru.bitel.bgbilling.kernel.contract.balance.server.ConvergenceBalance;
import ru.bitel.bgbilling.kernel.contract.balance.server.ConvergenceBalanceManager;
import ru.bitel.bgbilling.modules.tv.common.bean.TvAccount;
import ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.BillingEntry;
import ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.BillingException;
import ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.BillingException_Exception;
import ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.BillingServiceWS;
import ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.CustomerAccountInfo;
import ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.ServiceSpecification;
import ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.TimeFrame;
import ru.bitel.bgbilling.modules.tv.server.bean.TvAccountDao;
import ru.bitel.bgbilling.modules.tv.server.bean.TvAccountDetailDao;
import ru.bitel.common.TimeUtils;

@WebService(endpointInterface = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.BillingServiceWS")
public class BillingServiceWSImpl
	extends AbstractService
	implements BillingServiceWS
{
	private TvAccountDao tvAccountDao;

	private TvAccountDao getTvAccountDao()
	{
		if( tvAccountDao == null )
		{
			tvAccountDao = new TvAccountDao( getConnection(), moduleId );
		}
		return tvAccountDao;
	}

	private BillingException_Exception newException( String message )
	{
		BillingException exception = new BillingException();
		exception.setMessage( message );

		return new BillingException_Exception( message, exception );
	}

	private TvAccount getTvAccount( String accountNumber, Date time )
		throws BillingException_Exception
	{
		try
		{
			TvAccount result = getTvAccountDao().get( accountNumber, time );
			if( result == null )
			{
				throw newException( "Аккаунт " + accountNumber + " не найден." );
			}

			return result;
		}
		catch( Exception ex )
		{
		    logError( ex );

			throw newException( ex.getMessage() );
		}
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "")
	@RequestWrapper(localName = "queryCustomerAccountInfo", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryCustomerAccountInfo")
	@ResponseWrapper(localName = "queryCustomerAccountInfoResponse", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryCustomerAccountInfoResponse")
	public CustomerAccountInfo queryCustomerAccountInfo( @WebParam(name = "arg0", targetNamespace = "") String accountNumber )
		throws BillingException_Exception
	{
	    getLogger().info( "queryCustomerAccountInfo" );

		Date time = new Date();
		TvAccount tvAccount = getTvAccount( accountNumber, time );

		try
		{
			ConvergenceBalance balance = ConvergenceBalanceManager.getInstance().getBalance( getConnectionSet(), tvAccount.getContractId(), time.getTime() );

			CustomerAccountInfo result = new CustomerAccountInfo();
			result.setAccountNumber( accountNumber );
			result.setBalance( balance.getBalance().doubleValue() );
			result.setCreditLimit( balance.getLimit().doubleValue() );

			return result;
		}
		catch( BGException ex )
		{
		    logError( ex );

			throw newException( ex.getMessage() );
		}
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "")
	@RequestWrapper(localName = "querySummByService", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QuerySummByService")
	@ResponseWrapper(localName = "querySummByServiceResponse", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QuerySummByServiceResponse")
	public BigDecimal querySummByService( @WebParam(name = "arg0", targetNamespace = "") String accountNumber,
										  @WebParam(name = "arg1", targetNamespace = "") ServiceSpecification serviceSpecification,
										  @WebParam(name = "arg2", targetNamespace = "") TimeFrame timeFrame )
		throws BillingException_Exception
	{
	    getLogger().info( "querySummByService" );
	    getLogger().info( serviceSpecification.getType() );
	    getLogger().info( TimeUtils.format( timeFrame.getStartTime().toGregorianCalendar(), "dd.MM.yyyy HH:mm:ss" ) );
	    getLogger().info( TimeUtils.format( timeFrame.getEndTime().toGregorianCalendar(), "dd.MM.yyyy HH:mm:ss" ) );

		Date time = new Date();
		TvAccount tvAccount = getTvAccount( accountNumber, time );

		try
		{
			// BTV
			if( "BtvServiceSpec".equals( serviceSpecification.getType() ) )
			{
				ServerContext context = ServerContext.get();

				try
				{
					return TvAccountDetailDao.getAccount( context.getConnection(), moduleId, tvAccount.getId(), Collections.singleton( 24 ),
														  timeFrame.getStartTime().toGregorianCalendar().getTime(),
														  timeFrame.getEndTime().toGregorianCalendar().getTime() );
				}
				catch( Exception ex )
				{
				    logError( ex );
				}

				return BigDecimal.ZERO;
			}
			// VOD
			else if( "VodServiceSpec".equals( serviceSpecification.getType() ) )
			{
				ServerContext context = ServerContext.get();
				
				try
				{
					return TvAccountDetailDao.getAccount( context.getConnection(), moduleId, tvAccount.getId(), Collections.singleton( 26 ),
														  timeFrame.getStartTime().toGregorianCalendar().getTime(),
														  timeFrame.getEndTime().toGregorianCalendar().getTime() );
				}
				catch( Exception ex )
				{
				    logError( ex );
				}

				return BigDecimal.ZERO;
			}

			return null;
		}
		catch( Exception ex )
		{
		    logError( ex );

			throw newException( ex.getMessage() );
		}
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "")
	@RequestWrapper(localName = "queryAvailableServicesByAN", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryAvailableServicesByAN")
	@ResponseWrapper(localName = "queryAvailableServicesByANResponse", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryAvailableServicesByANResponse")
	public List<ServiceSpecification> queryAvailableServicesByAN( @WebParam(name = "arg0", targetNamespace = "") String accountNumber )
		throws BillingException_Exception
	{
	    getLogger().info( "queryAvailableServicesByAN" );
		return null;
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "")
	@RequestWrapper(localName = "queryAvailableServicesByANAndST", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryAvailableServicesByANAndST")
	@ResponseWrapper(localName = "queryAvailableServicesByANAndSTResponse", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryAvailableServicesByANAndSTResponse")
	public List<ServiceSpecification> queryAvailableServicesByANAndST( @WebParam(name = "arg0", targetNamespace = "") String accountNumber,
																	   @WebParam(name = "arg1", targetNamespace = "") String arg1 )
		throws BillingException_Exception
	{
	    getLogger().info( "queryAvailableServicesByANAndST" );
		return null;
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "")
	@RequestWrapper(localName = "queryBillingEntries", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryBillingEntries")
	@ResponseWrapper(localName = "queryBillingEntriesResponse", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryBillingEntriesResponse")
	public List<BillingEntry> queryBillingEntries( @WebParam(name = "arg0", targetNamespace = "") String accountNumber,
												   @WebParam(name = "arg1", targetNamespace = "") ServiceSpecification serviceSpecification,
												   @WebParam(name = "arg2", targetNamespace = "") TimeFrame timeFrame )
		throws BillingException_Exception
	{
	    getLogger().info( "queryBillingEntries" );
		return null;
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "")
	@RequestWrapper(localName = "queryBillingEntriesByANAndTF", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryBillingEntriesByANAndTF")
	@ResponseWrapper(localName = "queryBillingEntriesByANAndTFResponse", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryBillingEntriesByANAndTFResponse")
	public List<BillingEntry> queryBillingEntriesByANAndTF( @WebParam(name = "arg0", targetNamespace = "") String accountNumber,
															@WebParam(name = "arg1", targetNamespace = "") TimeFrame timeFrame )
		throws BillingException_Exception
	{
	    getLogger().info( "queryBillingEntriesByANAndTF" );
		return null;
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "")
	@RequestWrapper(localName = "queryReserve", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryReserve")
	@ResponseWrapper(localName = "queryReserveResponse", targetNamespace = "http://ws.external.push.adapter.billing.integration.iptv.oss.cti.ru/", className = "ru.bitel.bgbilling.modules.tv.dyn.cti.tve.ws.billing.QueryReserveResponse")
	public List<BillingEntry> queryReserve( @WebParam(name = "arg0", targetNamespace = "") String accountNumber,
											@WebParam(name = "arg1", targetNamespace = "") TimeFrame timeFrame )
		throws BillingException_Exception
	{
	    getLogger().info( "queryReserve" );
		return null;
	}
}