import { fromJS } from "immutable";
import whatsappReducer from "../reducer";
import {
  URL_META_TAGS_REQUEST,
  URL_META_TAGS_SUCCESS,
  URL_META_TAGS_FAILURE,
  URL_META_TAGS_RESET,
  UPLOAD_WHATSAPP_ASSET_PROCESSING,
  UPLOAD_WHATSAPP_ASSET_COMPLETED,
  UPLOAD_WHATSAPP_ASSET_FAILED,
  UPLOAD_WHATSAPP_ASSET_TIMEOUT,
  CLEAR_WHATSAPP_ASSET,
} from "../constants";
import { mockData } from "./mockData";

describe("whatsapp reducer", () => {
  it.concurrent("Reducer : URL_META_TAGS_REQUEST", () => {
    const state = fromJS({
      getMetaTagsRequest: false,
      metaTagsDetails: {},
      getMetaTagsError: '',
    });
    const action = { type: URL_META_TAGS_REQUEST };
    const expectedResult = state
      .set("getMetaTagsRequest", true)
      .set("metaTagsDetails", {});
    expect(whatsappReducer(state, action)).toEqual(expectedResult);
  });

  it.concurrent("Reducer : URL_META_TAGS_SUCCESS", () => {
    const state = fromJS({
      getMetaTagsRequest: false,
      metaTagsDetails: {},
      getMetaTagsError: '',
    });
    const action = { type: URL_META_TAGS_SUCCESS, data: mockData.metaTagsMock };
    const expectedResult = state
      .set("getMetaTagsRequest", false)
      .set("metaTagsDetails", mockData.metaTagsMock);
    expect(whatsappReducer(state, action)).toEqual(expectedResult);
  });

  it.concurrent("Reducer : URL_META_TAGS_FAILURE", () => {
    const state = fromJS({
      getMetaTagsRequest: false,
      metaTagsDetails: {},
      getMetaTagsError: '',
    });
    const action = { type: URL_META_TAGS_FAILURE, error: 'error' };
    const expectedResult = state
      .set("getMetaTagsRequest", false)
      .set("metaTagsDetails", {})
      .set("getMetaTagsError", 'error');
    expect(whatsappReducer(state, action)).toEqual(expectedResult);
  });

  it.concurrent("Reducer : URL_META_TAGS_RESET", () => {
    const state = fromJS({
      getMetaTagsRequest: false,
      metaTagsDetails: {},
      getMetaTagsError: '',
    });
    const action = { type: URL_META_TAGS_RESET };
    const expectedResult = state
      .set("metaTagsDetails", {});
    expect(whatsappReducer(state, action)).toEqual(expectedResult);
  });

  describe("Async upload processing state management", () => {
    const mockAsset = {
      _id: "asset-123",
      type: "IMAGE",
      url: "https://example.com/image.jpg",
    };

    it.concurrent("Reducer : UPLOAD_WHATSAPP_ASSET_PROCESSING", () => {
      const state = fromJS({
        uploadedAssetData: {},
        assetProcessing: {},
        uploadAssetSuccess: false,
        assetUploading: false,
      });
      const action = {
        type: UPLOAD_WHATSAPP_ASSET_PROCESSING,
        payload: {
          assetId: "asset-123",
          asset: mockAsset,
          processingStatus: "processing",
        },
      };
      const result = whatsappReducer(state, action);
      
      expect(result.get("uploadAssetSuccess")).toBe(false);
      expect(result.get("assetUploading")).toBe(true);
      expect(result.getIn(["assetProcessing", "asset-123", "status"])).toBe("processing");
      expect(result.getIn(["assetProcessing", "asset-123", "asset"])).toEqual(fromJS(mockAsset));
      expect(result.getIn(["assetProcessing", "asset-123", "startTime"])).toBeDefined();
      expect(result.getIn(["assetProcessing", "asset-123", "error"])).toBe(null);
    });

    it.concurrent("Reducer : UPLOAD_WHATSAPP_ASSET_COMPLETED without templateType", () => {
      const state = fromJS({
        uploadedAssetData: {},
        assetProcessing: {
          "asset-123": {
            status: "processing",
            asset: mockAsset,
          },
        },
        uploadAssetSuccess: false,
        assetUploading: true,
      });
      const action = {
        type: UPLOAD_WHATSAPP_ASSET_COMPLETED,
        payload: {
          assetId: "asset-123",
          asset: mockAsset,
        },
      };
      const result = whatsappReducer(state, action);
      
      expect(result.get("uploadAssetSuccess")).toBe(true);
      expect(result.get("assetUploading")).toBe(false);
      expect(result.get("uploadedAssetData")).toEqual(fromJS(mockAsset));
      expect(result.getIn(["assetProcessing", "asset-123", "status"])).toBe("completed");
      expect(result.getIn(["assetProcessing", "asset-123", "asset"])).toEqual(fromJS(mockAsset));
      expect(result.getIn(["assetProcessing", "asset-123", "error"])).toBe(null);
    });

    it.concurrent("Reducer : UPLOAD_WHATSAPP_ASSET_COMPLETED with templateType", () => {
      const state = fromJS({
        uploadedAssetData: {},
        uploadedAssetData2: {},
        assetProcessing: {
          "asset-123": {
            status: "processing",
            asset: mockAsset,
          },
        },
        uploadAssetSuccess: false,
        assetUploading: true,
      });
      const action = {
        type: UPLOAD_WHATSAPP_ASSET_COMPLETED,
        payload: {
          assetId: "asset-123",
          asset: mockAsset,
        },
        templateType: 2,
      };
      const result = whatsappReducer(state, action);
      
      expect(result.get("uploadAssetSuccess")).toBe(true);
      expect(result.get("assetUploading")).toBe(false);
      expect(result.get("uploadedAssetData2")).toEqual(fromJS(mockAsset));
      expect(result.getIn(["assetProcessing", "asset-123", "status"])).toBe("completed");
    });

    it.concurrent("Reducer : UPLOAD_WHATSAPP_ASSET_FAILED", () => {
      const state = fromJS({
        assetProcessing: {
          "asset-123": {
            status: "processing",
            asset: mockAsset,
          },
        },
        uploadAssetSuccess: false,
        assetUploading: true,
      });
      const action = {
        type: UPLOAD_WHATSAPP_ASSET_FAILED,
        payload: {
          assetId: "asset-123",
          error: "Processing failed",
        },
      };
      const result = whatsappReducer(state, action);
      
      expect(result.get("uploadAssetSuccess")).toBe(false);
      expect(result.get("assetUploading")).toBe(false);
      expect(result.getIn(["assetProcessing", "asset-123", "status"])).toBe("failed");
      expect(result.getIn(["assetProcessing", "asset-123", "error"])).toBe("Processing failed");
    });

    it.concurrent("Reducer : UPLOAD_WHATSAPP_ASSET_TIMEOUT", () => {
      const state = fromJS({
        assetProcessing: {
          "asset-123": {
            status: "processing",
            asset: mockAsset,
          },
        },
        uploadAssetSuccess: false,
        assetUploading: true,
      });
      const action = {
        type: UPLOAD_WHATSAPP_ASSET_TIMEOUT,
        payload: {
          assetId: "asset-123",
          message: "Asset processing is taking longer than expected",
        },
      };
      const result = whatsappReducer(state, action);
      
      expect(result.get("uploadAssetSuccess")).toBe(false);
      expect(result.get("assetUploading")).toBe(false);
      expect(result.getIn(["assetProcessing", "asset-123", "status"])).toBe("timeout");
      expect(result.getIn(["assetProcessing", "asset-123", "error"])).toBe("Asset processing is taking longer than expected");
    });

    it.concurrent("Reducer : CLEAR_WHATSAPP_ASSET without templateType", () => {
      const state = fromJS({
        uploadedAssetData: mockAsset,
        assetProcessing: {
          "asset-123": {
            status: "completed",
            asset: mockAsset,
          },
        },
      });
      const action = {
        type: CLEAR_WHATSAPP_ASSET,
      };
      const result = whatsappReducer(state, action);
      
      expect(result.has("uploadedAssetData")).toBe(false);
      expect(result.get("assetProcessing")).toEqual(fromJS({}));
    });

    it.concurrent("Reducer : CLEAR_WHATSAPP_ASSET with templateType", () => {
      const state = fromJS({
        uploadedAssetData: {},
        uploadedAssetData2: mockAsset,
        assetProcessing: {
          "asset-123": {
            status: "completed",
            asset: mockAsset,
          },
        },
      });
      const action = {
        type: CLEAR_WHATSAPP_ASSET,
        templateType: 2,
      };
      const result = whatsappReducer(state, action);
      
      expect(result.has("uploadedAssetData2")).toBe(false);
      expect(result.get("assetProcessing")).toEqual(fromJS({}));
    });
  });
});
