import io
import uuid

import requests

from helix.calculators.calculator import Calculator
from helix.constants import redis_constant, sql_constant
from helix.constants.system_type import SystemType
from helix.csv_builder import CsvBuilder
from helix.doc_gen_params_builder import DocGenParamsBuilder
from helix.helpers.camel_case import convert_dict_keys_to_snake_case
from helix.json_builder import JsonBuilder
from helix.presenters.image_presenter import ImagePresenter
from helix.Services.doc_gen_service import DocGenService
from helix.Services.s3_helper import s3_upload
from helix.session_manager import SessionManager


def get_site_characterization_from_sales_force(session, base_url):
    '''
    @base_url: Avoid URL_NOT_RESET errors
    '''
    access_token = session['sales_force_token']
    sfid = session['SFID']
    helix_id = session['id']
    url = base_url + '/services/apexrest/v1/HelixRoofDetails'
    headers = {'Authorization': 'Bearer {}'.format(access_token)}
    result = requests.get(url, headers=headers, params={'SFID': sfid, 'helix_session_id': helix_id})
    if result.status_code == 200:
        data = result.json()
        if data:
            data = convert_sales_force_data_format_to_helix(data)
        return data
    else:
        print('Error while getting data from Sales Force: {}'.format(result.status_code))
        print(result.content)


def convert_sales_force_data_format_to_helix(data):
    data = convert_dict_keys_to_snake_case(data)

    if data['system_type'] == 'Single-Tilt':
        data['system_type'] = SystemType.singleTilt.value
    elif data['system_type'] == 'Dual-Tilt':
        data['system_type'] = SystemType.dualTilt.value

    data['ballast_block_weight'] = data['ballast_weight']
    data['max_system_pressure'] = data['max_psf'] = data['system_pressure']
    return data
    # data['spectral_response_acceleration']


def export_to_sfdc(session_id):
    step = 'Exporting to SFDC'
    try:
        # 1. Load User Values
        step = 'Loading User Values'
        session = {'id': session_id}
        db_session = sql_constant.sql_session_maker()
        session_manager = SessionManager(session, redis_constant.redis_store, db_session)
        user_values = session_manager.user_values()
        calculator = Calculator(user_values)

        # 2. Generate BOM CSV file
        step = 'Generating BOM'
        bom = calculator.compute_bom()
        csv_file = CsvBuilder().build_bom_output(bom)
        # 2.1 Generate BOM CSV file
        step = 'Generating BOM as JSON'
        json_str = JsonBuilder().build_bom_output(bom)

        # 3. Generate DOCUMENTATION PDF file
        step = 'Generating Documentation'
        image_presenter = ImagePresenter(user_values.system_type(), user_values.module_type())
        doc_gen_service = DocGenService(requests, DocGenParamsBuilder(user_values, user_values.system_type(), calculator, image_presenter))
        document = doc_gen_service.generate() # Call external service

        # 4. Get Uploaded DXF file in the Helix system
        step = 'Loading uploaded DXF'
        dxf_contents = session_manager.site.dxf_file or session_manager.site.cad_file
        # dxf_filename = session_manager.site.dxf_file_name

        # 5. Save CSV/PDF/DXF files into AWS-S3
        step = 'Uploading to S3'
        filename = uuid.uuid4().hex
        bom_csv_url = s3_upload(io.StringIO(csv_file), filename=filename + '.csv')
        bom_json_url = s3_upload(io.StringIO(json_str), filename=filename + '.json')
        doc_url = s3_upload(io.BytesIO(document), filename=filename + '.pdf')
        if dxf_contents: # Optional
            dxf_url = s3_upload(io.StringIO(dxf_contents), filename=filename + '.dxf')
        else:
            dxf_url = None

        # 6. Notify SFDC system with an API request
        step = 'Notifying SFDC'
        SFDC_API_URL = 'https://localhost:8443/' # FIXME
        data = {
            'dxf_url': dxf_url,
            'bom_csv_url': bom_csv_url,
            'bom_json_url': bom_json_url,
            'documentation_url': doc_url,
        }
        print(data)
        # result = requests.post(SFDC_API_URL, data=data, timeout=30)

        # 7. Internal logs
        # if result.status_code != 200: # FIXME
        #     print('')
        # else:
        #     print('')

        db_session.close()
        return data
        # return result.status_code
    except Exception as e:
        msg = 'Error while {} for session {}'.format(step, session_id)
        print(msg)
        raise e
