import csv
import io


REQUIRED_COLUMNS = {'name', 'email', 'national_id', 'phone'}


class CsvParser:

    def validate(self, file_content):
        """Parse CSV content and validate required columns.

        Args:
            file_content: raw CSV string or bytes.

        Returns:
            dict with 'valid_rows' (list of dicts) and 'errors' (list of str).
        """
        if isinstance(file_content, bytes):
            file_content = file_content.decode('utf-8-sig')

        errors = []
        valid_rows = []

        reader = csv.DictReader(io.StringIO(file_content))

        if not reader.fieldnames:
            return {'valid_rows': [], 'errors': ['Empty CSV file or missing header row']}

        header_set = {col.strip().lower() for col in reader.fieldnames}
        missing = REQUIRED_COLUMNS - header_set
        if missing:
            return {
                'valid_rows': [],
                'errors': [f"Missing required columns: {', '.join(sorted(missing))}"],
            }

        for idx, row in enumerate(reader, start=2):
            parsed = self.parse_row(row)
            row_errors = []

            if not parsed.get('name'):
                row_errors.append(f"Row {idx}: 'name' is required")
            if not parsed.get('email'):
                row_errors.append(f"Row {idx}: 'email' is required")
            if not parsed.get('national_id'):
                row_errors.append(f"Row {idx}: 'national_id' is required")

            if row_errors:
                errors.extend(row_errors)
            else:
                valid_rows.append(parsed)

        return {'valid_rows': valid_rows, 'errors': errors}

    def parse_row(self, row):
        """Normalize a single CSV row.

        Args:
            row: dict from csv.DictReader.

        Returns:
            dict with trimmed, normalized values.
        """
        normalized = {}
        for key, value in row.items():
            clean_key = key.strip().lower()
            normalized[clean_key] = value.strip() if value else ''
        return normalized
