Error saving matches: Error: Score validation failed: status: `IN_PLAY` is not a valid enum value for path `status`.
    at ValidationError.inspect (C:\Node js programs\Football App\football-app-backend\node_modules\mongoose\lib\error\validation.js:50:26)
    at formatValue (node:internal/util/inspect:805:19)
    at inspect (node:internal/util/inspect:364:10)
    at formatWithOptionsInternal (node:internal/util/inspect:2298:40)
    at formatWithOptions (node:internal/util/inspect:2160:10)
    at console.value (node:internal/console/constructor:351:14)
    at console.warn (node:internal/console/constructor:384:61)
    at saveMatches (C:\Node js programs\Football App\football-app-backend\taskQueue\matchUpdateQueue.js:157:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async fetchAndUpdateMatches (C:\Node js programs\Football App\football-app-backend\taskQueue\matchUpdateQueue.js:109:5) {
  errors: {
    status: ValidatorError: `IN_PLAY` is not a valid enum value for path `status`.
        at validate (C:\Node js programs\Football App\football-app-backend\node_modules\mongoose\lib\schemaType.js:1385:13)
        at SchemaType.doValidate (C:\Node js programs\Football App\football-app-backend\node_modules\mongoose\lib\schemaType.js:1369:7)
        at C:\Node js programs\Football App\football-app-backend\node_modules\mongoose\lib\document.js:3065:18
        at process.processTicksAndRejections (node:internal/process/task_queues:77:11) {
      properties: [Object],
      kind: 'enum',
      path: 'status',
      value: 'IN_PLAY',
      reason: undefined,
      [Symbol(mongoose#validatorError)]: true
    }
  },
  _message: 'Score validation failed'
}
Error fetching and updating matches: Score validation failed: status: `IN_PLAY` is not a valid enum value for path `status`.



// models/Score.js

const mongoose = require("mongoose");

const TeamSchema = new mongoose.Schema(
  {
    id: {
      type: Number,
      required: true,
    },
    name: {
      type: String,
      required: true,
    },
    shortName: {
      type: String,
      required: true,
      default: "",
    },
    tla: {
      type: String,
      required: true,
      uppercase: true,
      minlength: 1,
      maxlength: 3,
    },
    crest: {
      type: String,
      required: true,
      match: /^https?:\/\/.+\.(png|jpg|jpeg|svg)$/,
    },
  },
  { _id: false }
);

const ScoreSchema = new mongoose.Schema(
  {
    id: {
      type: Number,
      required: true,
      unique: true,
    },
    utcDate: {
      type: Date,
      required: true,
    },
    status: {
      type: String,
      required: true,
      enum: [
        "SCHEDULED",
        "LIVE",
        // "INPLAY",
        "FINISHED",
        "PAUSED",
        "CANCELLED",
        "POSTPONED",
        "TIMED",
      ],
    },
    league: {
      type: String,
      required: true,
      default: "Other",
    },
    homeTeam: {
      type: TeamSchema,
      required: true,
    },
    awayTeam: {
      type: TeamSchema,
      required: true,
    },
    score: {
      winner: {
        type: String,
        enum: ["HOME_TEAM", "AWAY_TEAM", "DRAW", null],
        default: null,
      },
      duration: {
        type: String,
        required: true,
        enum: ["REGULAR", "EXTRA_TIME", "PENALTY"],
      },
      fullTime: {
        home: { type: Number, default: null },
        away: { type: Number, default: null },
      },
      halfTime: {
        home: { type: Number, default: null },
        away: { type: Number, default: null },
      },
    },
    odds: {
      type: Number,
      min: 0,
      required: true,
    },
    avgP: {
      type: Number,
      min: 0,
      max: 100,
      required: true,
    },
    avgG: {
      type: Number,
      min: 0,
      required: true,
    },
    cG: {
      type: Number,
      min: 0,
      required: true,
    },
    BTS: {
      type: String,
      enum: ["Yes", "No"],
      required: true,
    },
    FTS: {
      type: String,
      enum: ["Yes", "No"],
      required: true,
    },
    cOver25: {
      type: String,
      enum: ["Yes", "No"],
      required: true,
    },
  },
  {
    timestamps: true,
  }
);

// Indexes for optimized queries
ScoreSchema.index({ id: 1 });
ScoreSchema.index({ league: 1, status: 1 });

// Export the model
module.exports = mongoose.model("Score", ScoreSchema);


// taskQueue/matchUpdateQueue.js

const axios = require("axios");
const mongoose = require("mongoose");
const Score = require("../models/Score"); // Ensure the correct path

// Define league IDs and their names
const leagueIds = {
  2014: "La Liga",
  2021: "Premier League",
  2002: "Bundesliga",
  2019: "Serie A",
  2015: "Ligue 1",
  2001: "UEFA Champions League",
  2146: "UEFA Europa League",
};

/**
 * Fetches live scores from the API, transforms them, and saves to the database.
 */
async function fetchAndUpdateMatches() {
  try {
    const apiUrl = "https://api.football-data.org/v4/matches";
    const response = await axios.get(apiUrl, {
      headers: { "X-Auth-Token": process.env.API_FOOTBALL_KEY },
      params: {
        dateFrom: new Date(Date.now() - 2*24 * 60 * 60 * 1000) // 24 hours ago
          .toISOString()
          .split("T")[0],
        dateTo: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // 7 days ahead
          .toISOString()
          .split("T")[0],
      },
    });

    if (!response.data || !response.data.matches) {
      console.error("No match data received from API.");
      return;
    }

    const transformedMatches = response.data.matches.map((match) => {
      const leagueName = leagueIds[match.competition.id] || "Other";

      const homeTeam = {
        id: match.homeTeam.id,
        name: match.homeTeam.name,
        shortName: match.homeTeam.shortName || "",
        tla: match.homeTeam.tla || "",
        crest: match.homeTeam.crest || "",
      };

      const awayTeam = {
        id: match.awayTeam.id,
        name: match.awayTeam.name,
        shortName: match.awayTeam.shortName || "",
        tla: match.awayTeam.tla || "",
        crest: match.awayTeam.crest || "",
      };

       const score = {
         winner: match.score.winner,
         duration: match.score.duration
           ? match.score.duration.toUpperCase()
           : "REGULAR",
         fullTime: {
           home: match.score.fullTime?.home ?? null, // Use ?? instead of ||
           away: match.score.fullTime?.away ?? null, // Use ?? instead of ||
         },
         halfTime: {
           home: match.score.halfTime?.home ?? null, // Consistent use of ??
           away: match.score.halfTime?.away ?? null, // Consistent use of ??
         },
       };
       let status = match.status.toUpperCase();
       if (status === "IN_PLAY") {
         status = "IN_PLAY"; // This ensures it matches the enum value exactly
       } else if (
         ![
           "SCHEDULED",
           "LIVE",
           "FINISHED",
           "PAUSED",
           "CANCELLED",
           "POSTPONED",
           "TIMED",
         ].includes(status)
       ) {
         status = "SCHEDULED"; // Default to SCHEDULED if it's an unknown status
       }
      return {
        id: match.id,
        utcDate: new Date(match.utcDate),
        status: status,
        league: leagueName,
        homeTeam: homeTeam,
        awayTeam: awayTeam,
        score: score,
        odds: parseFloat(Math.random().toFixed(2)),
        avgP: parseFloat((Math.random() * 100).toFixed(2)),
        avgG: parseFloat((Math.random() * 5).toFixed(2)),
        cG: Math.floor(Math.random() * 10),
        BTS: Math.random() > 0.5 ? "Yes" : "No",
        FTS: Math.random() > 0.5 ? "Yes" : "No",
        cOver25: Math.random() > 0.5 ? "Yes" : "No",
      };
    });

    // Save matches to the database
    await saveMatches(transformedMatches);

    console.log("Fetched and saved live scores to DB");
  } catch (error) {
    if (error.response) {
      console.error(
        `Error fetching matches: ${error.response.status} - ${error.response.statusText}`
      );
    } else {
      console.error("Error fetching and updating matches:", error.message);
    }
  }
}

/**
 * Saves matches to the database and maintains only the latest batch.
 * @param {Array} matches - Array of match objects to save.
 */
async function saveMatches(matches) {
  try {
    if (!Array.isArray(matches) || matches.length === 0) {
      console.warn("No matches to save.");
      return;
    }

    // Start a session for transaction
    const session = await mongoose.startSession();
    session.startTransaction();
    try {
      // Delete all existing matches
      await Score.deleteMany({}, { session });
      console.log("Deleted all previous matches.");

      // Insert the new batch's matches
      await Score.insertMany(matches, { session });
      console.log(`Inserted ${matches.length} new matches.`);

      // Commit the transaction
      await session.commitTransaction();
      session.endSession();
    } catch (error) {
      // Abort the transaction on error
      await session.abortTransaction();
      session.endSession();
      console.error("Error during transaction, aborted changes.", error);
      throw error;
    }
  } catch (error) {
    console.error("Error saving matches:", error);
    throw error; // Propagate the error to be handled by the caller
  }
}

module.exports = { fetchAndUpdateMatches };


// controllers/scoresController.js

const Score = require("../models/Score"); // Ensure the correct path

/**
 * Retrieves the latest live scores from the database.
 * Route: GET /api/scores
 */
async function scoresController(req, res) {
  try {
    // Fetch matches from the latest batch
    const latestMatchBatch = await Score.findOne()
      .sort({ createdAt: -1 })
      .select("batchId")
      .lean();

    if (!latestMatchBatch) {
      return res.status(404).json({
        message: "No live scores available at the moment.",
      });
    }

    const latestBatchId = latestMatchBatch.batchId;

    // Fetch all matches in the latest batch
    const matches = await Score.find({ batchId: latestBatchId })
      .sort({ utcDate: 1 }) // Optional: sort matches by date
      .lean();

    if (!matches || matches.length === 0) {
      return res.status(404).json({
        message: "No live scores available in the latest batch.",
      });
    }

    // Group matches by league
    const groupedMatches = matches.reduce((acc, match) => {
      if (!acc[match.league]) {
        acc[match.league] = [];
      }
      acc[match.league].push(match);
      return acc;
    }, {});

    res.status(200).json({
      batchId: latestBatchId,
      totalMatches: matches.length,
      data: groupedMatches,
    });
  } catch (error) {
    console.error("Error fetching scores from DB:", error.message);
    res.status(500).json({
      message: "Unable to retrieve live scores from the database.",
    });
  }
}

module.exports = scoresController;


Can you resolve this error