import json

class PiParsers:
    @staticmethod
    def parse_serp_response(raw_data, market, workspace_name, search_engine_name, date, category_map=None, manual_duplication=None):
        """
        Transforms the nested 'Bulk Search Results' JSON into a flat list of dicts.
        """
        flat_rows = []
        
        # The API returns a list of objects (one per search term)
        for item in raw_data:
            search_term = item.get('searchTerm')
            
            # Determine Category
            category = ""
            if category_map:
                category = category_map.get(search_term, "")

            results = item.get('results', [])
            previous_pos = None

            # Helper to create a row
            def create_row(r_url, r_pos, r_feat, r_title, r_att):
                row = {
                    'Date': date,
                    'Market': market,
                    'SearchTerm': search_term,
                    'URL': r_url,
                    'Position': r_pos,
                    'SERPFeature': r_feat,
                    'PageTitle': r_title,
                    'SearchEngine': search_engine_name,
                    'Attributes': json.dumps(r_att) if r_att else None,
                    'Category': category,
                    'Workspace': workspace_name
                }
                return row

            if results:
                for res in results:
                    # Handle "Fill Down" logic for position if null
                    pos = res.get('position')
                    if pos is None:
                        pos = previous_pos
                    
                    # Only add if we have a valid position (based on your logic)
                    if pos is not None:
                        row = create_row(res.get('url'), pos, res.get('feature'), res.get('title'), res.get('attributes'))
                        flat_rows.append(row)

                        # Handle Manual Duplication
                        if manual_duplication and search_term in manual_duplication:
                            dup_row = row.copy()
                            dup_row['Category'] = manual_duplication[search_term]
                            flat_rows.append(dup_row)
                    
                    previous_pos = pos
            else:
                # Handle terms with no results if needed
                pass
                
        return flat_rows

    @staticmethod
    def build_category_map(pi_client, workspace_id):
        """Helper to build {term: stg_name} map"""
        mapping = {}
        stgs = pi_client.get_stgs(workspace_id)
        for stg in stgs:
            terms = pi_client.get_search_terms(workspace_id, stg['id'])
            for term in terms:
                t_text = term if isinstance(term, str) else term.get('term')
                mapping[t_text] = stg['name']
        return mapping


    # --- Existing SERP Parser ---
    @staticmethod
    def parse_serp_response(raw_data, market, workspace_name, search_engine_name, date, category_map=None, manual_duplication=None):
        # ... (Keep the code from the previous answer here) ...
        flat_rows = []
        for item in raw_data:
            search_term = item.get('searchTerm')
            category = category_map.get(search_term, "") if category_map else ""
            results = item.get('results', [])
            previous_pos = None

            def create_row(r_url, r_pos, r_feat, r_title, r_att):
                return {
                    'Date': date, 'Market': market, 'SearchTerm': search_term,
                    'URL': r_url, 'Position': r_pos, 'SERPFeature': r_feat,
                    'PageTitle': r_title, 'SearchEngine': search_engine_name,
                    'Attributes': json.dumps(r_att) if r_att else None,
                    'Category': category, 'Workspace': workspace_name
                }

            if results:
                for res in results:
                    pos = res.get('position')
                    if pos is None: pos = previous_pos
                    if pos is not None:
                        row = create_row(res.get('url'), pos, res.get('feature'), res.get('title'), res.get('attributes'))
                        flat_rows.append(row)
                        if manual_duplication and search_term in manual_duplication:
                            dup = row.copy()
                            dup['Category'] = manual_duplication[search_term]
                            flat_rows.append(dup)
                    previous_pos = pos
            else:
                # Optional: Handle no results
                pass
        return flat_rows

    # --- NEW: Volume Parser ---
    @staticmethod
    def parse_volume_data(volume_data, stg_name, stg_terms, workspace_name):
        """
        Matches bulk volume data to specific STG terms and flattens the monthly data.
        """
        rows = []
        # Create a lookup for the bulk data to make it fast
        volume_lookup = {item.get('search-term'): item for item in volume_data}

        for term in stg_terms:
            # Handle if term is string or object
            term_text = term if isinstance(term, str) else term.get('term', '')
            
            if term_text in volume_lookup:
                item = volume_lookup[term_text]
                cpc = item.get('cpc', '')
                monthly_volume = item.get('monthly-volume', {})
                
                for month, vol in monthly_volume.items():
                    rows.append({
                        "Workspace": workspace_name,
                        "STG": stg_name,
                        "Search Term": term_text,
                        "Month": month,
                        "Search Volume": vol,
                        "CPC": cpc
                    })
        return rows

    @staticmethod
    def build_category_map(pi_client, workspace_id):
        # ... (Keep existing code) ...
        mapping = {}
        stgs = pi_client.get_stgs(workspace_id)
        for stg in stgs:
            terms = pi_client.get_search_terms(workspace_id, stg['id'])
            for term in terms:
                t_text = term if isinstance(term, str) else term.get('term')
                mapping[t_text] = stg['name']
        return mapping