package com.interplug.qcast.biz.object;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.interplug.qcast.biz.object.dto.ObjectRequest;
import com.interplug.qcast.biz.object.dto.ObjectResponse;
import com.interplug.qcast.biz.object.dto.PlanReqRequest;
import com.interplug.qcast.biz.object.dto.PlanReqResponse;
import com.interplug.qcast.biz.object.dto.PlanRequest;
import com.interplug.qcast.biz.object.dto.PlanResponse;
import com.interplug.qcast.biz.object.dto.PrefResponse;
import com.interplug.qcast.biz.object.dto.SaleStoreResponse;
import com.interplug.qcast.biz.object.dto.UploadRequest;
import com.interplug.qcast.biz.object.dto.UploadResponse;
import com.interplug.qcast.biz.object.dto.WindSpeedResponse;
import com.interplug.qcast.biz.storeFavorite.StoreFavoriteService;
import com.interplug.qcast.config.Exception.ErrorCode;
import com.interplug.qcast.config.Exception.QcastException;
import com.interplug.qcast.config.message.Messages;
import com.interplug.qcast.util.InterfaceQsp;
import io.micrometer.common.util.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.util.UriComponentsBuilder;

@Slf4j
@Service
@RequiredArgsConstructor
public class ObjectService {
  private final InterfaceQsp interfaceQsp;

  @Autowired Messages message;

  @Value("${file.ini.root.path}")
  private String baseDirPath;

  @Value("${qsp.url}")
  private String QSP_API_URL;

  private final ObjectMapper objectMapper;

  private final StoreFavoriteService storeFavoriteService;

  /**
   * 도도부현 목록 조회
   *
   * @return List<PrefResponse> 도도부현 목록
   * @throws Exception
   */
  public List<PrefResponse> selectPrefList() throws Exception {
    return objectMapper.selectPrefList();
  }

  /**
   * 발전시뮬레이션 지역 목록 조회
   *
   * @param prefId 도도부현 코드
   * @return List<PrefResponse> 발전시뮬레이션 지역 목록
   * @throws Exception
   */
  public List<PrefResponse> selectPrefAreaList(String prefId) throws Exception {
    return objectMapper.selectPrefAreaList(prefId);
  }

  /**
   * 기준 풍속 목록 조회
   *
   * @param city 지역코드
   * @return List<WindSpeedResponse> 기준 풍속 목록
   * @throws Exception
   */
  public List<WindSpeedResponse> selectWindSpeedList(String city) throws Exception {
    return objectMapper.selectWindSpeedList(city);
  }

  /**
   * 1차점 판매점 목록 조회
   *
   * @param saleStoreId 1차점 판매점 아이디
   * @param userId 유저 아이디
   * @return List<SaleStoreResponse> 1차점 판매점 목록
   * @throws Exception
   */
  public List<SaleStoreResponse> selectFirstSaleStoreList(String saleStoreId, String userId)
      throws Exception {
    // Validation
    if (StringUtils.isEmpty(saleStoreId)) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Sale Store ID"));
    }
    if (StringUtils.isEmpty(userId)) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "User ID"));
    }

    // 1차점 판매점 목록 조회
    List<SaleStoreResponse> storeList = new ArrayList<SaleStoreResponse>();

    if ("T01".equals(saleStoreId)) {
      storeList = objectMapper.selectSaleStoreFirstList(userId);
    }

    return storeList;
  }

  /**
   * 하위 판매점 목록 조회
   *
   * @param saleStoreId 판매점 아이디
   * @param firstFlg 1차점 판매점 여부
   * @param userId 유저 아이디
   * @return List<SaleStoreResponse> 하위 판매점 목록
   * @throws Exception
   */
  public List<SaleStoreResponse> selectSaleStoreList(
      String saleStoreId, String firstFlg, String userId) throws Exception {
    // Validation
    if (StringUtils.isEmpty(saleStoreId)) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Sale Store ID"));
    }
    if (StringUtils.isEmpty(userId)) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "User ID"));
    }

    // 판매점 목록 조회
    List<SaleStoreResponse> storeList = new ArrayList<SaleStoreResponse>();
    storeList = objectMapper.selectSaleStoreList(saleStoreId, firstFlg, userId);

    return storeList;
  }

  /**
   * 판매점 정보 상세 조회
   *
   * @param saleStoreId 판매점 아이디
   * @return SaleStoreResponse 판매점 상세 정보
   * @throws Exception
   */
  public SaleStoreResponse selectSaleStoreInfo(String saleStoreId) throws Exception {
    return objectMapper.selectSaleStoreInfo(saleStoreId);
  }

  /**
   * 물건정보 목록 조회
   *
   * @param objectRequest 물건정보 검색어 정보
   * @return List<ObjectResponse> 물건정보 목록
   * @throws Exception
   */
  public List<ObjectResponse> selectObjectList(ObjectRequest objectRequest) throws Exception {
    return objectMapper.selectObjectList(objectRequest);
  }

  /**
   * 물건정보 상세 조회
   *
   * @param objectNo 물건번호
   * @return ObjectResponse 물건정보 상세
   * @throws Exception
   */
  public ObjectResponse selectObjectDetail(String objectNo) throws Exception {
    // object 상세 정보 조회
    ObjectResponse objectResponse = objectMapper.selectObjectDetail(objectNo);

    if (objectResponse != null) {
      // Plan 목록 조회
      PlanRequest planRequest = new PlanRequest();
      planRequest.setObjectNo(objectNo);
      List<PlanResponse> planList = objectMapper.selectPlanList(planRequest);

      objectResponse.setPlanList(planList);
    }

    return objectResponse;
  }

  /**
   * 물건정보 저장
   *
   * @param objectRequest 물건정보
   * @return ObjectResponse 물건정보 저장 결과 값
   * @throws Exception
   */
  public ObjectResponse insertObject(ObjectRequest objectRequest) throws Exception {
    int result = 0;
    String objectNo = "";

    // Validation
    if (StringUtils.isEmpty(objectRequest.getSaleStoreId())) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Sale Store ID"));
    }
    if (StringUtils.isEmpty(objectRequest.getSaleStoreLevel())) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Sale Store Level"));
    }

    objectRequest.setSourceOrigin("QCAST_III");

    // 물건번호 등록/조회
    if ("0".equals(objectRequest.getTempFlg())) {
      objectRequest.setDelFlg("1");
      objectRequest.setOrgDelFlg("0");
      objectRequest.setTempFlg("0");
      objectRequest.setTempDelFlg("0");

      result += objectMapper.insertObjectNo(objectRequest);
      objectNo = objectMapper.selectObjectNo(objectRequest);
    } else if ("1".equals(objectRequest.getTempFlg())) {
      objectRequest.setDelFlg("1");
      objectRequest.setOrgDelFlg("1");
      objectRequest.setTempFlg("1");
      objectRequest.setTempDelFlg("0");

      // 임시저장인 경우 임시 물건번호 생성 yyyymmddhh24missSSS_랜덤문자 3개
      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
      Calendar dateTime = Calendar.getInstance();
      objectNo = sdf.format(dateTime.getTime());

      objectNo = "T" + objectNo.substring(2) + RandomStringUtils.randomAlphanumeric(3);
      objectNo = objectNo.toUpperCase();
    }

    objectRequest.setObjectNo(objectNo);

    // 물건정보 등록
    objectRequest.setAddress(
        ((!StringUtils.isEmpty(objectRequest.getAddress())) ? objectRequest.getAddress() : ""));
    objectRequest.setAddresseeCompanyName(
        objectRequest.getObjectName() + ' ' + objectRequest.getObjectNameOmit());
    objectRequest.setAddresseeCompanyNameOmit(objectRequest.getObjectNameOmit());
    objectRequest.setContentsPath(baseDirPath + "\\\\" + objectRequest.getObjectNo());
    result += objectMapper.insertObject(objectRequest);
    result += objectMapper.updateObjectDelivery(objectRequest);

    // 디폴트 Plan 등록
    PlanRequest planRequest = new PlanRequest();
    planRequest.setObjectNo(objectNo);
    planRequest.setRoofKindId("0");
    planRequest.setCharger(objectRequest.getReceiveUser());
    planRequest.setStatus("1");
    planRequest.setDelFlg("0");
    planRequest.setNorthArrangement("0");
    planRequest.setDiffRoofEnabled("0");
    planRequest.setOrderFlg("0");
    planRequest.setUserId(objectRequest.getUserId());
    result += objectMapper.insertPlan(planRequest);

    // 플랜번호 존재 시 물건번호 업데이트
    if ("0".equals(objectRequest.getTempFlg())
        && !StringUtils.isEmpty(objectRequest.getPlanReqNo())) {
      PlanReqResponse response = null;

      PlanReqRequest planReqRequest = new PlanReqRequest();
      planReqRequest.setSaleStoreId(objectRequest.getSaleStoreId());
      planReqRequest.setSaleStoreLevel(objectRequest.getSaleStoreLevel());
      planReqRequest.setPlanReqNo(objectRequest.getPlanReqNo());
      planReqRequest.setObjectNo(objectRequest.getObjectNo());

      String strResponse =
          interfaceQsp.callApi(
              HttpMethod.POST, QSP_API_URL + "/api/planReq/updateObjectNo", planReqRequest);
      if (!"".equals(strResponse)) {
        com.fasterxml.jackson.databind.ObjectMapper om =
            new com.fasterxml.jackson.databind.ObjectMapper()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        response = om.readValue(strResponse, PlanReqResponse.class);

        Map<String, Object> map = (Map<String, Object>) response.getResult();
        if ("E".equals(String.valueOf(map.get("resultCode")))) {
          throw new QcastException(
              ErrorCode.INTERNAL_SERVER_ERROR, String.valueOf(map.get("resultMsg")));
        }
      }
    }

    // 결과 데이터 리턴
    ObjectResponse objectResponse = new ObjectResponse();
    objectResponse.setObjectNo(objectNo);
    objectResponse.setPlanNo(planRequest.getPlanNo());

    return objectResponse;
  }

  /**
   * 물건정보 수정
   *
   * @param objectRequest 물건정보
   * @return ObjectResponse 물건정보 수정 결과 값
   * @throws Exception
   */
  public ObjectResponse updateObject(ObjectRequest objectRequest) throws Exception {
    int result = 0;
    boolean tempChgFlg = false;

    // Validation
    if (StringUtils.isEmpty(objectRequest.getSaleStoreId())) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Sale Store ID"));
    }
    if (StringUtils.isEmpty(objectRequest.getSaleStoreLevel())) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Sale Store Level"));
    }

    // object 상세 정보 조회
    ObjectResponse objectResponse = objectMapper.selectObjectDetail(objectRequest.getObjectNo());

    if (objectResponse != null) {
      // 임시저장에서 저장상태 바뀌었는지 확인
      if ("1".equals(objectResponse.getTempFlg()) && "0".equals(objectRequest.getTempFlg())) {
        tempChgFlg = true;

        result += objectMapper.insertObjectNo(objectRequest);
        objectRequest.setNewObjectNo(objectMapper.selectObjectNo(objectRequest));
      }

      // 물건정보 수정
      objectRequest.setAddress(
          ((!StringUtils.isEmpty(objectRequest.getAddress())) ? objectRequest.getAddress() : ""));
      objectRequest.setAddresseeCompanyName(
          objectRequest.getObjectName() + ' ' + objectRequest.getObjectNameOmit());
      objectRequest.setAddresseeCompanyNameOmit(objectRequest.getObjectNameOmit());
      objectRequest.setContentsPath(
          baseDirPath
              + "\\\\"
              + (tempChgFlg ? objectRequest.getNewObjectNo() : objectRequest.getObjectNo()));
      result += objectMapper.updateObject(objectRequest);

      // 임시저장에서 저장상태로 돌리기
      if (tempChgFlg) {
        objectMapper.updateObjectNoChange(objectRequest);
        objectMapper.updatePlanObjectNoChange(objectRequest);

        // 플랜번호 존재 시 물건번호 업데이트
        if (!StringUtils.isEmpty(objectRequest.getPlanReqNo())) {
          PlanReqResponse response = null;

          PlanReqRequest planReqRequest = new PlanReqRequest();
          planReqRequest.setSaleStoreId(objectRequest.getSaleStoreId());
          planReqRequest.setSaleStoreLevel(objectRequest.getSaleStoreLevel());
          planReqRequest.setPlanReqNo(objectRequest.getPlanReqNo());
          planReqRequest.setObjectNo(objectRequest.getNewObjectNo());

          String strResponse =
              interfaceQsp.callApi(
                  HttpMethod.POST, QSP_API_URL + "/api/planReq/updateObjectNo", planReqRequest);
          if (!"".equals(strResponse)) {
            com.fasterxml.jackson.databind.ObjectMapper om =
                new com.fasterxml.jackson.databind.ObjectMapper()
                    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            response = om.readValue(strResponse, PlanReqResponse.class);

            Map<String, Object> map = (Map<String, Object>) response.getResult();
            if ("E".equals(String.valueOf(map.get("resultCode")))) {
              throw new QcastException(
                  ErrorCode.INTERNAL_SERVER_ERROR, String.valueOf(map.get("resultMsg")));
            }
          }
        }
      }
    }

    // 모든 변경 완료 후 재호출
    objectResponse =
        objectMapper.selectObjectDetail(
            (tempChgFlg ? objectRequest.getNewObjectNo() : objectRequest.getObjectNo()));
    return objectResponse;
  }

  /**
   * 물건정보 삭제
   *
   * @param objectRequest 물건정보
   * @return int 결과 값
   * @throws Exception
   */
  public int deleteObject(ObjectRequest objectRequest) throws Exception {
    int result = 0;

    // Validation
    if (StringUtils.isEmpty(objectRequest.getObjectNo())) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Object No"));
    }

    // object 상세 정보 조회
    ObjectResponse objectResponse = objectMapper.selectObjectDetail(objectRequest.getObjectNo());
    if (objectResponse != null) {
      // 설계의뢰 번호가 존재하고 물건정보에 견적서가 없을 경우 QSP 설계의뢰 물건번호 초기화
      if (!StringUtils.isEmpty(objectResponse.getPlanReqNo())
          && objectResponse.getEstimateTotCnt() == 0) {
        PlanReqResponse response = null;

        PlanReqRequest planReqRequest = new PlanReqRequest();
        planReqRequest.setSaleStoreId(objectResponse.getSaleStoreId());
        planReqRequest.setSaleStoreLevel(objectResponse.getSaleStoreLevel());
        planReqRequest.setObjectNo(objectResponse.getObjectNo());
        planReqRequest.setPlanReqNo(objectResponse.getPlanReqNo());
        planReqRequest.setDelFlg("1");

        String strResponse =
            interfaceQsp.callApi(
                HttpMethod.POST, QSP_API_URL + "/api/planReq/updateObjectNo", planReqRequest);
        if (!"".equals(strResponse)) {
          com.fasterxml.jackson.databind.ObjectMapper om =
              new com.fasterxml.jackson.databind.ObjectMapper()
                  .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
          response = om.readValue(strResponse, PlanReqResponse.class);

          Map<String, Object> map = (Map<String, Object>) response.getResult();
          if ("E".equals(String.valueOf(map.get("resultCode")))) {
            throw new QcastException(
                ErrorCode.INTERNAL_SERVER_ERROR, String.valueOf(map.get("resultMsg")));
          }
        }
      }

      // 물건정보 삭제
      result = objectMapper.deleteObject(objectRequest);
    }

    return result;
  }

  /**
   * 신규 플랜정보 추가
   *
   * @param planRequest 플랜정보
   * @return String 추가 플랜번호
   * @throws Exception
   */
  public String insertPlan(PlanRequest planRequest) throws Exception {
    // Validation
    if (StringUtils.isEmpty(planRequest.getObjectNo())) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Object No"));
    }

    // Plan 추가 가능 체크
    List<PlanResponse> planList = objectMapper.selectPlanList(planRequest);
    if (planList.size() > 9) {
      throw new QcastException(
          ErrorCode.INTERNAL_SERVER_ERROR, message.getMessage("common.message.plan.save.limit"));
    }

    // 추가 Plan 등록
    planRequest.setRoofKindId("0");
    planRequest.setStatus("1");
    planRequest.setDelFlg("0");
    planRequest.setNorthArrangement("0");
    planRequest.setDiffRoofEnabled("0");
    planRequest.setOrderFlg("0");

    objectMapper.insertPlan(planRequest);

    return planRequest.getPlanNo();
  }

  /**
   * 플랜정보 삭제
   *
   * @param planRequest 플랜정보
   * @throws Exception
   */
  public void deletePlan(PlanRequest planRequest) throws Exception {
    // Validation
    if (StringUtils.isEmpty(planRequest.getObjectNo())) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Object No"));
    }
    if (StringUtils.isEmpty(planRequest.getPlanNo())) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Plan No"));
    }

    // Plan 삭제 가능 체크
    List<PlanResponse> planList = objectMapper.selectPlanList(planRequest);
    if (planList.size() < 2) {
      throw new QcastException(
          ErrorCode.INTERNAL_SERVER_ERROR, message.getMessage("common.message.plan.delete.limit"));
    }

    // Plan 삭제
    objectMapper.deletePlan(planRequest);
  }

  /**
   * 설계의뢰 목록 조회
   *
   * @param planReqRequest 설계의뢰 요청 정보
   * @return PlanReqResponse 설계의뢰 응답 정보
   * @throws Exception
   */
  public PlanReqResponse selectPlanReqList(PlanReqRequest planReqRequest) throws Exception {

    // Validation
    if (StringUtils.isEmpty(planReqRequest.getSaleStoreId())) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Sale Store ID"));
    }
    if (StringUtils.isEmpty(planReqRequest.getSaleStoreLevel())) {
      throw new QcastException(
          ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Sale Store Level"));
    }

    PlanReqResponse response = null;

    /* [1]. QSP API (url + param) Setting */
    String encodedSchPlanReqNo =
        URLEncoder.encode(
            StringUtils.isEmpty(planReqRequest.getSchPlanReqNo())
                ? ""
                : planReqRequest.getSchPlanReqNo(),
            StandardCharsets.UTF_8);
    String encodedSchTitle =
        URLEncoder.encode(
            StringUtils.isEmpty(planReqRequest.getSchTitle()) ? "" : planReqRequest.getSchTitle(),
            StandardCharsets.UTF_8);
    String encodedSchAddress =
        URLEncoder.encode(
            StringUtils.isEmpty(planReqRequest.getSchAddress())
                ? ""
                : planReqRequest.getSchAddress(),
            StandardCharsets.UTF_8);

    String encodedSchSaleStoreName =
        URLEncoder.encode(
            StringUtils.isEmpty(planReqRequest.getSchSaleStoreName())
                ? ""
                : planReqRequest.getSchSaleStoreName(),
            StandardCharsets.UTF_8);
    String encodedSchPlanReqName =
        URLEncoder.encode(
            StringUtils.isEmpty(planReqRequest.getSchPlanReqName())
                ? ""
                : planReqRequest.getSchPlanReqName(),
            StandardCharsets.UTF_8);

    String url = QSP_API_URL + "/api/planReq/list";

    String apiUrl =
        UriComponentsBuilder.fromHttpUrl(url)
            .queryParam("saleStoreId", planReqRequest.getSaleStoreId())
            .queryParam("saleStoreLevel", planReqRequest.getSaleStoreLevel())
            .queryParam("schPlanReqNo", encodedSchPlanReqNo)
            .queryParam("schTitle", encodedSchTitle)
            .queryParam("schAddress", encodedSchAddress)
            .queryParam("schSaleStoreName", encodedSchSaleStoreName)
            .queryParam("schPlanReqName", encodedSchPlanReqName)
            .queryParam("schPlanStatCd", planReqRequest.getSchPlanStatCd())
            .queryParam("schDateGbn", planReqRequest.getSchDateGbn())
            .queryParam("schStartDt", planReqRequest.getSchStartDt())
            .queryParam("schEndDt", planReqRequest.getSchEndDt())
            .queryParam("startRow", planReqRequest.getStartRow())
            .queryParam("endRow", planReqRequest.getEndRow())
            .build()
            .toUriString();

    /* [2]. QSP API CALL -> Response */
    String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null);

    if (!"".equals(strResponse)) {
      com.fasterxml.jackson.databind.ObjectMapper om =
          new com.fasterxml.jackson.databind.ObjectMapper()
              .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

      response = om.readValue(strResponse, PlanReqResponse.class);
    } else {
      // [msg] No data
      throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data"));
    }

    return response;
  }

  /**
   * 물건정보 첨부파일 다운로드
   *
   * @param request Request
   * @param response Response
   * @param uploadRequest 첨부파일 요청 정보
   * @throws Exception
   */
  public void fileDownload(
      HttpServletRequest request, HttpServletResponse response, UploadRequest uploadRequest)
      throws Exception {

    InputStream inputStream = null;

    try {
      // 첨부파일 조회
      UploadResponse uploadResponse = objectMapper.selectUpload(uploadRequest);

      if (uploadResponse != null) {
        // 첨부파일 물리적 경로
        String filePath =
            baseDirPath
                + File.separator
                + uploadResponse.getObjectNo()
                + File.separator
                + uploadResponse.getFaileName();
        File file = new File(filePath);

        if (file.exists()) {
          // 파일 변환 타입
          String mimeType = URLConnection.guessContentTypeFromName(file.getName());
          if (mimeType == null) {
            mimeType = "application/octet-stream";
          }

          // 소스 파일 명
          String srcFileName = uploadResponse.getFaileName();
          srcFileName = URLEncoder.encode(srcFileName, "UTF-8").replaceAll("\\+", "%20");

          response.setHeader("Content-Transfer-Encoding", "binary;");
          response.setHeader("Pragma", "no-cache;");
          response.setHeader("Expires", "-1;");
          response.setHeader("Content-Disposition", "attachment; filename=\"" + srcFileName + "\"");
          response.setContentType(mimeType);
          response.setContentLength((int) file.length());

          inputStream = new BufferedInputStream(new FileInputStream(file));

          FileCopyUtils.copy(inputStream, response.getOutputStream());
        } else {
          throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR);
        }
      } else {
        throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR);
      }
    } catch (Exception e) {
      throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR);
    } finally {
      if (inputStream != null) {
        inputStream.close();
      }
    }
  }
}
